我正在尝试使用 NASM 打印单个字符或数字,目标是x86 GNU / Linux架构。
这是我正在使用的代码:
section .text
global _start
_start:
; Linux printing preparation
mov eax,4
mov ebx,1
; Print 'A' character
mov ecx,'A' ; ecx should contain the value to print
mov edx,1 ; edx should contain how many characters to print
int 80h
; System exit
mov eax,1
mov ebx,0
int 80h
然而,运行此代码不会打印任何内容。我做错了什么?
答案 0 :(得分:8)
ecx
应包含指向char缓冲区开头的指针。所以你必须把你的缓冲区放在内存中。您可以执行以下操作:
; Print 'A' character
mov eax, 4 ; __NR_write from asm/unistd_32.h (32-bit int 0x80 ABI)
mov ebx, 1 ; stdout fileno
push 'A'
mov ecx, esp ; esp now points to your char
mov edx, 1 ; edx should contain how many characters to print
int 80h ; sys_write(1, "A", 1)
; return value in EAX = 1 (byte written), or error (-errno)
add esp, 4 ; restore esp if necessary
如果可以覆盖堆叠中的任何内容,您可以mov byte [esp], 'A'
或其他任何地址。
或者您可以在section .rodata
中使用字符数组,而不是动态存储。
答案 1 :(得分:1)
您正在执行的系统调用期望ecx
在内存中包含一个地址。这可以是任意文字地址(即,在您的代码中,"A"
转换为地址041h
),堆栈上的地址或程序中标签定义的地址。
下面是在内存中定义一个字节并将其写入终端的标准输出流的示例:
section .rodata ; This section contains read-only data
buffer: db 'A' ; Define our single character in memory
section .text
global start
_start:
; Prints the letter 'A', then exits
mov eax, 4 ; sys_write()
mov ebx, 1 ; ... to STDOUT
mov ecx, buffer ; ... using the following memory address
mov edx, 1 ; ... and only print one character
int 80h ; SYSCALL
mov eax, 1 ; Return to system
mov ebx, 0 ; Exit zero, success
int 80h ; SYSCALL