我在一个名为 cpuid.s 的文件中有一段代码:
.code32
.section .data
output:
.asciz "The processor Vendor ID is '%s'\n"
.section .bss
.lcomm buffer, 12
.section .text
.globl main
main:
movl $0, %eax
cpuid
movl $buffer, %edi
movl %ebx, (%edi)
movl %edx, 4(%edi)
movl %ecx, 8(%edi)
pushl $buffer
pushl $output
call printf
addl $8, %esp
pushl $0
call exit
我的操作系统类型是64位,所以我添加.code32
进行编译,我在Ubuntu14.04上使用gcc来编译这段代码:
gcc -o demo cpuid.s
它已成功编译。然后我在终端上运行demo,但它会提示Segmentation fault (core dumped)
。
所以我用gdb来调试。然后gdb提示:
Program received signal SIGSEGV, Segmentation fault.
__printf (format=0x601078 <buffer> "GenuineIntel") at printf.c:28
28 printf.c: No such file or directory.
请指出我的问题是什么以及如何解决。感谢。
答案 0 :(得分:2)
在64位(amd64)进程中,只能运行64位代码。 .code32
指令强制汇编程序将指令汇编为32位代码,但它并没有使它神奇地起作用。相反,处理器仍然处于64位模式,将您的32位机器代码解释为64位机器代码,通常会带来灾难性后果。
如果要编写32位汇编,则需要将整个程序编译为32位程序。这会导致Linux将处理器设置为程序的32位兼容模式,因此32位代码运行正常。使用gcc,可以通过在编译的所有阶段将-m32
传递给编译器来完成。在当前示例中,只需删除.code32
指令,然后使用
gcc -m32 -o demo test.s
答案 1 :(得分:1)
这里带走的关键点是:
&#34; bitness&#34;您的可执行文件(ELF)文件和&#34; bitness&#34; GAS发出的机器代码是独立的。
正如FUZxxl所提到的,.code32
告诉GAS发出32位机器代码。但是,GCC(驱动GAS)最终会生成 64位 ELF文件。
当你执行这个程序时,内核说&#34;这是一个64位的ELF,我将以64位模式运行它。&#34;当CPU(在64位模式下)尝试执行32位指令时,这当然不能很好地结束。
添加-m32
(如评论中所述)告诉GCC做两件事:
libc