GAS读取程序遇到“分段错误”的论点

时间:2014-07-19 10:10:29

标签: assembly nasm gas param debian-based

我开始学习Assembly,我选择的编译器是GNU AS。唯一可怕的是,关于AS,它的语法和用户指南的文档很少。

我编写了一个hello world程序,它读取一个文本文件(文件路径是程序的第一个参数)并将其内容显示给stdout。但是当我运行程序时,它总是说“段故障”。稍微修改一下源代码,我发现在读取程序的输入参数时遇到了问题。如果我把文件路径放在源代码中,没有问题,但如果我从输入参数中读取它,就会发生“分段错误”。

这是关于读取输入参数

的源代码
# get file name from argument and put in to ebx
movl 8(%esp), %ebx

# open the file
# movl $path, %ebx
movl $5, %eax
movl $0, %ecx
movl $0666, %edx
int $0x80

我已经搜索了很多关于在GAS中阅读输入参数的内容,但我发现的只是一篇非常好的文章:NASM - Linux Getting command line parameters。我复制了代码并将其更改为x64(我的机器是kali x64)。有趣的是,我重新遇到了“分段错误”。什么是悲伤的一天!!!

因此,如果有人在Linux中使用过assemby,特别是使用GAS或NASM,请帮我解决这个问题。

1000+感谢(如果可能的话)为您提供帮助

丛。

update1:​​这是我的完整源代码

.global main
.text
main:
# get file name from parameter and put in to ebx
movl 8(%esp), %ebx
# read path in source code
# movl $path, %ebx

# open the file
# movl $path, %ebx
movl $5, %eax
movl $0, %ecx
movl $0666, %edx
int $0x80

# read the file
movl %eax, %ebx
movl $3, %eax
movl $buf, %ecx
movl $bufSize, %edx
int $0x80

# write to stdout
movl %ebx, %ebp
movl $4, %eax
movl $1, %ebx
movl $buf, %ecx
int $0x80

# close the file
movl $6, %eax
movl %ebp, %ebx
int $0x80

exit:
movl $1, %eax
movl $0, %ebx
int $0x80

.data
path:
.asciz "./hello_world.c"
.bss
.equ bufSize, 1024
.lcomm buf, bufSize

更新2:我的操作系统是x86_64,这是我在x86_64中编程程序集时遇到的很多问题的根源。在@ user35443和@Jester的帮助下,我终于可以找到一些解决方法:编译到x86 elf文件,而不是x64 elf。源代码与上面相同,稍微更改main到_start。因为我在x86_64上编译x86,我需要一些东西:apt-get install gcc-multilib,之后,编译是直截了当的:as --32 readfile.s -o readfile.o && ld -m elf_i386 readfile.o -o readfile && ./readfile some_text_file(ps:我不知道为什么gcc -m32 readfile.s封锁错误)< / p>

.global _start
.text
_start:
# get file name from parameter and put in to ebx
movl 8(%esp), %ebx
# movl $path, %ebx

# open the file
# movl $path, %ebx
movl $5, %eax
movl $0, %ecx
movl $0666, %edx 
int $0x80

# read the file
movl %eax, %ebx
movl $3, %eax
movl $buf, %ecx
movl $bufSize, %edx
int $0x80

# write to stdout
movl %ebx, %ebp
movl $4, %eax
movl $1, %ebx
movl $buf, %ecx
# size of write is %edx
int $0x80

# close the file
movl $6, %eax
movl %ebp, %ebx
int $0x80

exit:
movl $1, %eax
movl $0, %ebx
int $0x80

.data
path:
.asciz "./hello_world.c"
.bss
.equ bufSize, 1024
.lcomm buf, bufSize

因为我专注于x86_64,我会让问题打开几天,这是我的x84_64的源代码,我找不到问题的根源(也许我错误地使用了x86_64调用约定)。

.global main
.text
main:
# get file name from parameter and put in to rbx
movq 16(%rsp), %rbx
#movq $path, %rbx

# open the file
# movq $path, %rbx
movq $5, %rax
movq $0, %rcx
movq $0666, %rdx 
int $0x80

# read the file
movq %rax, %rbx
movq $3, %rax
movq $buf, %rcx
movq $bufSize, %rdx
int $0x80

# write to stdout
movq %rbx, %rbp
movq $4, %rax
movq $1, %rbx
movq $buf, %rcx
# size of write is %rdx
int $0x80

# close the file
movq $6, %rax
movq %rbp, %rbx
int $0x80

exit:
movq $1, %rax
movq $0, %rbx
int $0x80

.data
path:
.asciz "./hello_world.c"
.bss
.equ bufSize, 1024
.lcomm buf, bufSize

1 个答案:

答案 0 :(得分:1)

这是代码的64位端口:

.global main
.text
main:
push %rbx           # save rbx
# get file name from parameter and put in to rdi
# argv in rsi
# open the file
movq 8(%rsi), %rdi  # path
movl $0, %esi       # flags
movl $0666, %edx    # mode
movl $2, %eax       # SYS_OPEN
syscall
movl %eax, %ebx     # save fd

# read the file
movl %eax, %edi     # fd
leaq buf, %rsi      # buf
movl $bufSize, %edx # count
movl $0, %eax       # SYS_READ
syscall

# write to stdout
movl $1, %edi       # stdout
leaq buf, %rsi      # buf
movl %eax, %edx     # count
movl $1, %eax       # SYS_WRITE

syscall

# close the file
movl %ebx, %esi     # fd
movl $3, %eax       # SYS_CLOSE
syscall

exit:
xor %eax, %eax      # return 0
pop %rbx            # restore rbx
ret

.data
path:
.asciz "./hello_world.c"
.bss
.equ bufSize, 1024
.lcomm buf, bufSize

注意,使用来自使用libc的程序的原始系统调用不是一个好主意。使用exit系统调用尤其糟糕,因为这样就不会让c库关闭。我已经删除了退出系统调用,但保留了其他调用。对于64位,系统调用号和调用约定是不同的。您可以在wikipedia快速浏览一下,或阅读ABI文档了解全貌。