Ich habe mich dann doch einmal auf Assembler eingelassen. Ich möchte dabei ein kleines Programm schreiben, was von stdin liest und nach stdout schreibt, was in C so aussehen könnte:
cat.c
Code: Select all
#include <stdio.h>
int main(){
char c;
while( (c=getc(stdin)) != EOF)
putc(c, stdout);
return 0;
}
Der erste Schritt war natürlich ein "hello world!" (nutze Intel-Syntax):
hello.asm
Code: Select all
; from: Linux Assembly HOWTO
section .data ; section declaration
msg db "Hello, world!", 0xa ; our dear string 0ax is '\n'
len equ $ - msg ; length of our dear string
section .text ; section declartion
; a program needs at least .text
; we must export the entry point
; to the ELF linker or loader. They
global _start ; conventionally recognize start as
; their entry point. Use ld -e foo
; to override. the default
_start:
; write our string to stdout
; write(2) [ von mir eingefügt]
; #include <unistd.h>
;
; ssize_t write(int fd, const void *buf, size_t count);
; eax ebx ecx edx
mov edx, len ; third argument: message length
mov ecx, msg ; second argument: pointer to message to write
mov ebx, 1 ; first argument: file handle (stdout == 1)
mov eax,4 ; system call number (sys_write) [ nachzulesen in /usr/include/asm/unistd.h]
int 0x80 ; call kernel
; and exit
mov ebx, 0 ; first syscall argument: exit code
mov eax, 1 ; system call number (sys_exit)
int 0x80 ; call kernel
read.c
Code: Select all
void main(){
char buf[8];
buf[7] = '\n';
}
Code: Select all
(gdb) disassemble main
Dump of assembler code for function main:
0x08048354 <main+0>: push %ebp ; Inhalt von ebp auf Stack pushen
0x08048355 <main+1>: mov %esp,%ebp ; esp (Stackpointer) nach ebp schreiben
0x08048357 <main+3>: sub $0x8,%esp ; 0x8 von esp subtrahieren <- sind das unsere 8 Bytes?
0x0804835a <main+6>: and $0xfffffff0,%esp ; logisches UND auf esp und 0xfffffff0 ausfuehren
; Das heißt: die letzten zwei byte von esp auf Null setzen
; Wohin wird das Ergebnis geschrieben? nach esp?
0x0804835d <main+9>: mov $0x0,%eax ; 0x0 nach eax schreiben
0x08048362 <main+14>: sub %eax,%esp ; esp von eax abziehen und in eax schreiben
0x08048364 <main+16>: movb $0xa,0xffffffff(%ebp) ; 0xa an die letzte Stelle von ebp schreiben
; ( buf[7] = '\n' )
0x08048368 <main+20>: leave ; ???
0x08048369 <main+21>: ret ; return
0x0804836a <main+22>: nop ; keine Operation
0x0804836b <main+23>: nop
0x0804836c <main+24>: nop
0x0804836d <main+25>: nop
0x0804836e <main+26>: nop
0x0804836f <main+27>: nop
End of assembler dump.
So wie ich das sehe, beinhaltet esp die Addresse buf[7], zeigt also auf das Ende des Array. Das geht so ziemlich aus der Zeile <main+16> hervor. Ist das korrekt? Dann müsste man von dieser Addresse nur 7 Byte abziehen und würde auf buf[0] == buf zeigen. Das wäre dann 0xffffffc7(ebp).
Allerdings blicke ich im Gesamten irgendwie nicht durch. Ich habe zwar schon den Assembler-Code mit einem
Code: Select all
gcc -S -masm=intel --static -o cat.S cat.c
Die allgemeine Frage ist also: Wie realisiere ich, mir 1. Speicher zu verschaffen, 2. darauf per syscall zuzugreifen bzw. mir die richtige Addrese zu suchen und 3. das auch noch irgendwie mit einer Abfrage nach EOF in Verbindung zu bringen.
Desweiteren hätte ich die Frage, was ihr für eine Syntax bevorzugt - Intel oder AT&T - und natürlich aus welchen Gründen.
Gruß
Lateralus