本文主要是介绍《汇编语言程序设计》例子出现segmentation fault,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
照着例子抄写了一下,直接用的 gcc 编译,源码如下,因为不支持 pushl,所以改成了 pushq
#cpuid.s View the CPUID Vendor ID string using C library calls
.section .data
output:.asciz "The processor Vendor ID is %s \n".section .bss.lcomm buffer, 12.section .text
.global main
main:MOVL $0, %eaxcpuidMOVL $buffer, %edi MOVL %ebx, (%edi)MOVL %edx, 4(%edi)MOVL %ecx, 8(%edi)pushq $bufferpushq $outputcall printfaddl $8, %esppushq $0call exit
如果使用 pushl 的话,在x86_64 位下不支持,如下错误信息:
网上搜索到解决办法有 2 种,一种是在源码开头添加.code32 告诉编译器按照32位进行编译,另外一种是使用 pushq,q 即为 quad word 表示 8 字节长度的,即 64 位。编译通过后,运行时出现 segmentation fault。网上搜了很多,没有一样的,但很多相似的在调用 printf 的时候出现 segmentation fault,这个跟调用约定有关系,64 位和32 位还不一样,64 位下是通过寄存器和栈来传递参数的,而 32 位下则是通过栈来传递参数的。看上面的代码 pushq $buffer 和 pushq $output 就是入栈操作,而在 64 位下:整数参数(包含指针)依次放在 %rdi, %rsi, %rdx, %rcx, %r8, 和 %r9 寄存器中,如果调用的是可变参数的函数(比如printf), 寄存器%eax需记录下浮点参数的个数,找到一段可用的代码,修改如下:
.section .data
output:.string "The processor Vendor ID is %s \n".section .bss.lcomm buffer, 32.section .text
.global main
main:MOVL $0, %eaxcpuidMOVL $buffer, %edi MOVL %ebx, (%edi)MOVL %edx, 4(%edi)MOVL %ecx, 8(%edi)MOVQ $output, %rdi #需要用MOVQ 来操作64bit寄存器MOVQ $buffer, %rsi #同上MOVQ $0, %rax #同上pushq %r10pushq %r11call printfpopq %r11popq %r10ret
这篇关于《汇编语言程序设计》例子出现segmentation fault的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!