x86汇编中访问字符串字符及首字符打印失效问题求助
问题描述
从标准输入读取字符串后,输出该字符串并打印其首字符。编写的x86汇编代码能正常读取和输出字符串,但打印首字符的部分完全无效。编译命令为:gcc -m32 filename.S -o filename -no-pie
汇编代码如下:
.data mesaj: .space 11 # the string to be read formatScanf: .asciz "%s" formatPrintf: .asciz "%s" endl: .asciz "\n" .text .global main main: push $mesaj push $formatScanf call scanf pop %ebx pop %ebx push $mesaj push $formatPrintf call printf pop %ebx pop %ebx pushl $0 call fflush popl %ebx push $endl push $formatPrintf call printf pop %ebx pop %ebx pushl $0 call fflush popl %ebx # Print the first letter of the string movl $0, %edx mov $mesaj, %edi mov $4, %eax # System call number for write mov $1, %ebx # File descriptor: 1 for standard output mov $1, %ecx # Number of bytes to print movb (%edi), %dl # Load the first byte (character) of the string into DL register int $0x80 # Call the kernel to write the character pushl $0 call fflush popl %ebx movl $1, %eax movl $0, %ebx int $0x80
问题排查与修正
问题出在write系统调用的参数传递错误:
- Linux 32位系统调用
write的参数约定是:%eax:系统调用号(4对应write)%ebx:文件描述符(1是标准输出)%ecx:指向要写入数据的内存地址%edx:要写入的字节数
你的代码里错误地把%ecx设为1(字节数),把首字符放到%dl(%edx的低8位),这不符合系统调用的参数要求。write会把%ecx的值当作内存地址去取数据,而地址1是无效的,所以没有输出。
修正后的首字符打印代码如下:
# Print the first letter of the string mov $4, %eax # System call number for write mov $1, %ebx # File descriptor: 1 for standard output mov $mesaj, %ecx # 指向要输出的首字符的地址 mov $1, %edx # 要输出的字节数(1个字符) int $0x80 # Call the kernel to write the character
解释:
- 直接把
mesaj的地址传给%ecx,因为mesaj就是字符串首字符的内存位置 - 把要输出的字节数1放到
%edx - 不需要用到
%edi寄存器,直接用%ecx传递地址即可
这样修改后,write系统调用就能正确读取mesaj地址处的1个字节并输出到标准输出。
内容的提问来源于stack exchange,提问作者Cristi Dima
相关产品推荐
相关产品推荐

