我正在尝试使用此程序集程序打印一系列ascii字符。 我试图只使用寄存器,但没有太多运气。一切看起来都很好,但我是装配编程的新手,可能错过了一些明显的东西。任何见解将不胜感激。谢谢:)
强调文字 。文本 .global _start
_start:
movl $1, %edx
movl $65, %ebx
start_loop:
addl $1, %ebx
movl $0x04, %eax
int $0x80
cmpl $126, %ebx
jle start_loop
jmp start_loop
exit
movl $0, %ebx
movl $1, %eax
int $0x80
答案 0 :(得分:3)
您正在调用sys_write系统调用。 sys_write()接受三个参数,输出设备的文件描述符(对于stdout应为1),存储要打印的值的缓冲区的地址,以及要打印的数据的大小。因此,您必须将文件描述符存储在%ebx中,并将缓冲区的地址存储在%ecx中,并将数据的大小存储在%edx中。要存储文件描述符,可以使用以下指令。
movl $1, %ebx // store 1 (stdout) in ebx)
要存储您可以使用的数据大小:
movl $1, %edx // size is 1 byte
现在,你必须存储缓冲区的地址,你需要把你的数据放在内存中的某些地方,并且需要在%ecx中存储内存的地址。假设您希望将数据存储在堆栈中,那么您可以这样做:
subl $4, %esp // get 4 bytes of memory in the stack
movl $65, (%esp) // store data in the memory where esp points to
movl %esp, %ecx // store address of the data in the ecx
现在你可以发出int 0x80。
movl $04, %eax // store syscall number in eax
int $0x80 // issue the trap interrupt
作为一个整体,您可以编写以下代码:
movl $1, %ebx
subl $0x4, %esp
movl $64, (%esp)
start_loop:
movl (%esp), %eax
addl $1, %eax
movl %eax, (%esp)
movl %esp, %ecx
movl $1, %edx
movl $0x04, %eax
int $0x80
movl (%esp), %eax
cmpl $126, %eax
jle start_loop
addl $0x4, %esp
请参阅http://www.rulingminds.com/syscallspart2上的Linux系统调用Part2,以了解有关寄存器和系统调用用法的更多信息。
答案 1 :(得分:1)
“非常感谢您提供了丰富的答案,但有没有办法存储和检索要在寄存器中打印的值而不指向它?” - 这可能已被编辑成问题。
如果你坚持只使用系统调用(int $0x80
)与系统接口,那么答案是否定的。你必须以某种方式将缓冲区传递给write
并且rullingminds的答案适用。
使用libc putchar(3)
它是直截了当的。我使用%ebx
来保存ascii代码,因为这个寄存器是在函数调用之间保留的linux上。只需使用gcc filename.S
进行汇编(如果您使用的是x86_64,请记住使用-m32
)。
.text
.extern putchar
.global main
main:
# make room for argument to putchar on the stack
sub $4, %esp
# initialize ebx with first value to print
mov $'A', %ebx
1:
# give character to print as argument
mov %ebx, (%esp)
call putchar
# move to next character
inc %ebx
# are we done?
cmp $'~', %ebx
jle 1b
# print newline
movl $10, (%esp)
call putchar
# adjust stack back to normal
add $4, %esp
# return 0 from main
mov $0, %eax
ret