简体   繁体   English

用户输入和输出在我的汇编代码中不起作用

[英]User input and output doesn't work in my assembly code

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).您的代码中有迹象表明您在为 OS/X(BSD) 生成代码时可能一直在使用 Linux 教程。 Linux and OS/X have differing SYSCALL calling conventions. Linux 和 OS/X 具有不同的SYSCALL调用约定。 In OS/X 32-bit programs int 0x80 requires parameters (except the syscall in EAX ) to be passed on a stack.在 OS/X 32 位程序中int 0x80需要在堆栈上传递参数( EAX 中的系统调用除外)。

The important things to be aware of with 32-bit SYSCALL s via int 0x80 on OS/X are:在 OS/X 上通过int 0x80使用 32 位SYSCALL需要注意的重要事项是:

  • 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压入所有参数后,您必须在堆栈上分配额外的 4 个字节(一个DWORD
  • syscall number in the eax register eax 寄存器中的系统调用号
  • call by interrupt 0x80通过中断 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.在为int 0x80以相反的顺序将参数压入堆栈后,您必须在堆栈上分配额外的 4 个字节(一个DWORD )。 The value in that memory location on the stack doesn't matter.堆栈上该内存位置的值无关紧要。 This requirement is an artifact from an old UNIX convention .此要求是旧 UNIX 约定的产物

A list of the SYSCALL numbers and their parameters can be found in the APPLE header files . SYSCALL编号及其参数的列表可以在APPLE 头文件中找到 You'll need these SYSCALL s:您将需要这些SYSCALL

 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. and esp, -16仅当您需要将堆栈与 16 字节边界对齐作为未来堆栈操作的基线时才需要。 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 .如果您打算调用符合OS/X 32 位 ABI的外部函数,则堆栈应为 16 字节对齐,紧接在函数CALL 之前 This alignment is not necessary for system calls via int 0x80 .通过int 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM