用户输入和输出并不在我的组装code工作 [英] User input and output doesn't work in my assembly code
问题描述
下面的程序编译没有错误,但运行时不会提示任何输入和任何打印。有什么问题,我怎么能解决这个问题?
我使用这些命令汇编和链接:
的/ usr / local / bin目录/ NASM -f macho32 $ 1
LD -macosx_version_min 10.9.0 -lSystem -o运行$ filename.o -e _start -lc
我的code是:
部分。数据
;新行字符串
NEWLINE:DB为0xA,0xd中
长度:EQU $ -NEWLINE.bss段
INPT:RESD 1.text段
全球_start
_开始:
;读取字符
MOV EAX,0x3中
MOV EBX,为0x1
MOV ECX,INPT
MOV EDX,为0x1
INT 80H;打印字符
MOV EAX,为0x4
MOV EBX,为0x1
MOV ECX,INPT
MOV EDX,为0x1
INT 80H;输出后打印新行
MOV EAX,为0x4
MOV EBX,为0x1
MOV ECX,NEWLINE
MOV EDX,长度
INT 0x80的;终止
MOV EAX,为0x1
XOR EBX,EBX
INT 0x80的
有在code迹象表明,你可能会为OS / X(BSD)生产code时,已经使用的是Linux教程。 Linux和OS / X具有不同的 SYSCALL 的调用约定。在OS / X 32位程序 INT 0x80的
需要参数(除了系统调用中的 EAX 的)在堆栈上传递。
重要的事情要通过 0x80的INT
在OS / X是意识到与32位的 SYSCALL 取值
- 在栈上传递的参数,推从右至左
- 您必须分配在堆栈上额外的4个字节( DWORD 的),你把所有的参数之后
- 在EAX寄存器系统调用号
- 将0x80中断
通话
块引用>以相反的顺序推栈上的参数为
INT 0x80的
您必须在栈上分配额外的4个字节( DWORD 的)后。在堆栈上存储单元中的值无关紧要。此要求从旧的UNIX约定。的 SYSCALL 的数量和它们的参数可以在苹果的的头文件。你需要这些的 SYSCALL 取值:
1 AUE_EXIT ALL {无效出口(INT RVAL); }
3 AUE_NULL ALL {user_ssize_t阅读(INT FD,user_addr_t CBUF,user_size_t nbyte); }
4 AUE_NULL ALL {user_ssize_t写(INT FD,user_addr_t CBUF,user_size_t nbyte); }
块引用>我评论过一些例如code,这将是在功能上你可能一直在试图达到什么相似的:
部分。数据
;新行字符串
NEWLINE:DB为0xA,0xd中
长度:EQU $ -NEWLINE.bss段
INPT:RESD 1全球_start.text段
_开始:
和ESP,-16;在程序启动确保栈16字节对齐
;在本例中没有必要,因为我们不叫
;符合的OS / X的32位ABI外部函数 推DWORD 1;阅读1个字符
推DWORD INPT;输入缓冲区
推DWORD 0;标准输入= 0 FD
MOV EAX,3;系统调用SYS_READ
子ESP,4;额外的4个堆栈由INT 0x80的需要
INT 0x80的
ADD ESP,16;恢复堆栈 推DWORD 1;打印1个字符
推DWORD INPT;输出缓冲区=缓冲区我们读入字符
推DWORD 1;标准输出= 1 FD
MOV EAX,4;系统调用SYS_WRITE
子ESP,4;额外的4个堆栈由INT 0x80的需要
INT 0x80的
ADD ESP,16;恢复堆栈 推DWORD的长度;字符数写
推DWORD NEWLINE;写在NEWLINE字符串数据
推DWORD 1;标准输出= 1 FD
MOV EAX,4;系统调用SYS_WRITE
子ESP,4;额外的4个堆栈由INT 0x80的需要
INT 0x80的
ADD ESP,16;恢复堆栈 推DWORD 0;从程序返回值= 0
MOV EAX,1;系统调用sys_exit
子ESP,4;额外的4个堆栈由INT 0x80的需要
INT 0x80的的
和ESP,-16
是只需要如果你需要堆栈对齐到16字节边界作为未来堆栈操作的基准。如果您打算调用符合<一个外部函数href=\"https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4\"相对=nofollow> OS / X 32位ABI 的堆栈预计将对齐16字节立即preceding功能的呼叫的。这种一致性通过0x80的INT
是没有必要的系统调用。您应该能够组装和链接它:
NASM -f macho32 TEST.ASM -o test.o
LD -macosx_version_min 10.9.0测试-o -e test.o _start -lSystem和与运行:
./测试
The following program compiles without errors, but when run it doesn't prompt for any input and nothing prints. What's the problem, and how can I fix it?
I use these commands to assemble and link:
/usr/local/bin/nasm -f macho32 $1 ld -macosx_version_min 10.9.0 -lSystem -o run $filename.o -e _start -lc
My code is:
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
解决方案There are signs in your code that you may have been using a Linux tutorial when producing code for OS/X(BSD). Linux and OS/X have differing SYSCALL calling conventions. In OS/X 32-bit programs
int 0x80
requires parameters (except the syscall in EAX) to be passed on a stack.The important things to be aware of with 32-bit SYSCALLs via
int 0x80
on OS/X are:
- 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
After pushing arguments on the stack in reverse order for
int 0x80
you must allocate an additional 4 bytes (a DWORD) on the stack. The value in that memory location on the stack doesn't matter. This requirement is an artifact from an old UNIX convention.A list of the SYSCALL numbers and their parameters can be found in the APPLE header files. You'll need these 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); }
I have commented some example code that would be similar in functionality to what you may have been attempting to achieve:
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
The
and esp, -16
is only necessary if you need to align the stack to a 16-byte boundary as a baseline for future stack operations. If you intend to call external functions that conform to the OS/X 32-bit ABI the stack is expected to be 16-byte aligned immediately preceding a function CALL. This alignment is not necessary for system calls viaint 0x80
.You should be able to assemble and link it with:
nasm -f macho32 test.asm -o test.o ld -macosx_version_min 10.9.0 -o test test.o -e _start -lSystem
And run it with:
./test
这篇关于用户输入和输出并不在我的组装code工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!