用户输入和输出在我的汇编代码中不起作用
User input and output doesn't work in my assembly code
下面的程序编译没有错误,但是当 运行 它不提示输入任何内容,也没有打印任何内容。有什么问题,我该如何解决?
我使用这些命令 assemble 和 link:
/usr/local/bin/nasm -f macho32
ld -macosx_version_min 10.9.0 -lSystem -o run $filename.o -e _start -lc
我的代码是:
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
您的代码中有迹象表明您在为 OS/X(BSD) 生成代码时可能一直在使用 Linux 教程。 Linux 和 OS/X 有不同的 SYSCALL 调用约定。在 OS/X 中,32 位程序 int 0x80
需要在堆栈上传递参数(EAX 中的系统调用除外)。
在 OS/X 上通过 int 0x80
使用 32 位 SYSCALLs 需要注意的重要事项是:
- arguments passed on the stack, pushed right-to-left
- you must allocate an additional 4 bytes (a DWORD) on the stack after you push all the arguments
- syscall number in the eax register
- call by interrupt 0x80
在为 int 0x80
以相反顺序将参数压入堆栈后,您必须在堆栈上分配额外的 4 个字节(DWORD)。堆栈上该内存位置的值无关紧要。此要求是 old UNIX convention.
的产物
可以在 APPLE header files 中找到 SYSCALL 编号及其参数的列表。您将需要这些 SYSCALLs:
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); }
我已经评论了一些示例代码,它们在功能上与您可能一直试图实现的目标相似:
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
仅当您需要将堆栈对齐到 16 字节边界作为未来堆栈操作的基线时,才需要 and esp, -16
。如果您打算调用符合 OS/X 32-bit ABI 的外部函数,则堆栈应该是 16 字节对齐的,紧接在函数 CALL 之前。通过 int 0x80
.
的系统调用不需要这种对齐方式
您应该能够 assemble 和 link 它:
nasm -f macho32 test.asm -o test.o
ld -macosx_version_min 10.9.0 -o test test.o -e _start -lSystem
和运行它与:
./test
下面的程序编译没有错误,但是当 运行 它不提示输入任何内容,也没有打印任何内容。有什么问题,我该如何解决?
我使用这些命令 assemble 和 link:
/usr/local/bin/nasm -f macho32
ld -macosx_version_min 10.9.0 -lSystem -o run $filename.o -e _start -lc
我的代码是:
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
您的代码中有迹象表明您在为 OS/X(BSD) 生成代码时可能一直在使用 Linux 教程。 Linux 和 OS/X 有不同的 SYSCALL 调用约定。在 OS/X 中,32 位程序 int 0x80
需要在堆栈上传递参数(EAX 中的系统调用除外)。
在 OS/X 上通过 int 0x80
使用 32 位 SYSCALLs 需要注意的重要事项是:
- arguments passed on the stack, pushed right-to-left
- you must allocate an additional 4 bytes (a DWORD) on the stack after you push all the arguments
- syscall number in the eax register
- call by interrupt 0x80
在为 int 0x80
以相反顺序将参数压入堆栈后,您必须在堆栈上分配额外的 4 个字节(DWORD)。堆栈上该内存位置的值无关紧要。此要求是 old UNIX convention.
可以在 APPLE header files 中找到 SYSCALL 编号及其参数的列表。您将需要这些 SYSCALLs:
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); }
我已经评论了一些示例代码,它们在功能上与您可能一直试图实现的目标相似:
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
仅当您需要将堆栈对齐到 16 字节边界作为未来堆栈操作的基线时,才需要 and esp, -16
。如果您打算调用符合 OS/X 32-bit ABI 的外部函数,则堆栈应该是 16 字节对齐的,紧接在函数 CALL 之前。通过 int 0x80
.
您应该能够 assemble 和 link 它:
nasm -f macho32 test.asm -o test.o
ld -macosx_version_min 10.9.0 -o test test.o -e _start -lSystem
和运行它与:
./test