2016-03-19 18 views
3

Das folgende Programm kompiliert ohne Fehler, aber wenn es ausgeführt wird, fordert es keine Eingabe und nichts druckt. Was ist das Problem und wie kann ich es beheben?Benutzer Eingabe und Ausgabe funktioniert nicht in meinem Assembly Code

verwende ich diese Befehle zu montieren und Link:

/usr/local/bin/nasm -f macho32 $1 
ld -macosx_version_min 10.9.0 -lSystem -o run $filename.o -e _start -lc 

Mein Code ist:

section .data 
    ;New line string 
    NEWLINE: db 0xa, 0xd 
    LENGTH: equ $-NEWLINE 

section .bss  
INPT: resd 1 

section .text 
global _start 
_start: 


;Read character 
mov eax, 0x3 
mov ebx, 0x1 
mov ecx, INPT 
mov edx, 0x1 
int 80h 

;print character 
mov eax, 0x4 
mov ebx, 0x1 
mov ecx, INPT 
mov edx, 0x1 
int 80h 

;Print new line after the output 
mov eax, 0x4 
mov ebx, 0x1 
mov ecx, NEWLINE 
mov edx, LENGTH 
int 0x80 

;Terminate 
mov eax, 0x1 
xor ebx, ebx 
int 0x80 
+3

'int 0x80' anders auf OSX funktioniert. Parameter zu "int 0x80" (neben _EAX_) werden auf dem Stack in 32-Bit-Code nicht in Registern übergeben. Der Code, den Sie geschrieben haben, sieht so aus, als wäre er für Linux geschrieben worden. Ich würde ein [OS/X-Tutorial] empfehlen (https://filippo.io/making-system-calls-from-assembly-in-mac-os-x/). Auch die Systemrufnummern unterscheiden sich zwischen Linux und OSX. –

+1

Sobald Sie Ihren Code in OS/X konvertiert haben, sollten Sie beachten, dass Standardeingabe der Dateideskriptor 0 und Standardausgabe der Dateideskriptor 1 ist. Sie verwenden Standardausgabe (1) für Eingabe und Ausgabe, die nach Problemen fragt . –

+0

@Michael Petch Ja, Sie haben Recht, danke! – Strelok2014Strelok

Antwort

5

Es gibt Zeichen in Ihrem Code, den Sie ein Linux-Tutorial wurden verwendet, kann, wenn der Code produzieren für OS/X (BSD). Linux und OS/X haben unterschiedliche Aufrufkonventionen SYSCALL. In OS/X 32-Bit-Programmen int 0x80 erfordert Parameter (außer der syscall in EAX) auf einem Stapel übergeben werden.

Die wichtigen Dinge des mit 32-Bit-SYSCALL s über int 0x80 auf OS/X sind sich bewusst sein:

  • Argumente auf dem Stack übergeben, geschoben von rechts nach links
  • Sie müssen eine zusätzliche 4 Bytes (ein DWORD) auf dem Stapel zuzuteilen, nachdem Sie alle Argumente
  • syscall Nummer im EAX-Register schieben
  • Aufruf von Interrupt 0x80

Nach Argumente auf dem Stack in umgekehrter Reihenfolge für int 0x80 schieben müssen Sie weitere 4 Bytes (a DWORD) auf dem Stack zugeordnet werden. Der Wert in diesem Speicherplatz auf dem Stapel spielt keine Rolle. Diese Anforderung ist ein Artefakt von old UNIX convention.

Eine Liste der SYSCALL Zahlen und ihre Parameter könnenheader files im APPLE finden. Sie werden diese SYSCALL s benötigen:

1 AUE_EXIT ALL { void exit(int rval); } 
3 AUE_NULL ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); } 
4 AUE_NULL ALL { user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); } 

Ich habe einige Beispiel-Code kommentiert, die in der Funktionalität ähnlich sein würde, was Sie zu erreichen haben versucht können:

section .data 
    ;New line string 
    NEWLINE: db 0xa, 0xd 
    LENGTH: equ $-NEWLINE 

section .bss 
    INPT: resd 1 

global _start 

section .text 
_start: 
    and  esp, -16  ; Make sure stack is 16 byte aligned at program start 
          ;  not necessary in this example since we don't call 
          ;  external functions that conform to the OS/X 32-bit ABI 

    push dword 1  ; Read 1 character 
    push dword INPT ; Input buffer 
    push dword 0  ; Standard input = FD 0 
    mov  eax, 3  ; syscall sys_read 
    sub  esp, 4  ; Extra 4 bytes on stack needed by int 0x80 
    int  0x80 
    add  esp, 16  ; Restore stack 

    push dword 1  ; Print 1 character 
    push dword INPT ; Output buffer = buffer we read characters into 
    push dword 1  ; Standard output = FD 1 
    mov  eax, 4  ; syscall sys_write 
    sub  esp, 4  ; Extra 4 bytes on stack needed by int 0x80 
    int  0x80 
    add  esp, 16  ; Restore stack 

    push dword LENGTH ; Number of characters to write 
    push dword NEWLINE ; Write the data in the NEWLINE string 
    push dword 1  ; Standard output = FD 1 
    mov  eax, 4  ; syscall sys_write 
    sub  esp, 4  ; Extra 4 bytes on stack needed by int 0x80 
    int  0x80 
    add  esp, 16  ; Restore stack 

    push dword 0  ; Return value from program = 0 
    mov  eax, 1  ; syscall sys_exit 
    sub  esp, 4  ; Extra 4 bytes on stack needed by int 0x80 
    int  0x80 

Die and esp, -16 ist nur erforderlich, wenn Sie den Stapel auf eine 16-Byte-Grenze als Basis für zukünftige Stapeloperationen ausrichten müssen. Wenn Sie beabsichtigen, externe Funktionen aufzurufen, die der OS/X 32-bit ABI entsprechen, wird erwartet, dass der Stapel 16-Byte-ausgerichtet ist, unmittelbar vor einer Funktion CALL. Diese Ausrichtung ist für Systemaufrufe über int 0x80 nicht erforderlich.

sollten Sie in der Lage sein, sie zu montieren und verbinden mit:

nasm -f macho32 test.asm -o test.o 
ld -macosx_version_min 10.9.0 -o test test.o -e _start -lSystem 

und führen Sie es mit:

./test 
Verwandte Themen