在《汇编语言程序设计》这本书中,第4章有一个调用C语言printf函数打印的程序。在64位的操作系统上是不能够按书上的方法编译这段程序的。代码如下
#打印CPUID
.section .data
#初始化代码
output:
#12位CPUID
.asciz "The processor Venfor ID is '%s'\n"
.section .bss
#未初始化代码
.lcomm buffer,12
.section .text
.globl main
main:
movl $0,%eax#this is an instruction
cpuid#move the value output to edi
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
使用下面的代码编译就可以成功运行。 下面这种方式时候在调用C语言代码的时候使用。
as -32 -gstabs -o print_cpuid_c.o print_cpuid_c.s
gcc -m32 -g -o print_cpuid_c print_cpuid_c.s -fno-pie -no-pie
./print_cpuid_c
-gtabs 表示生成STABS(Symbol Table String),功能就是生成的二进制会多出额外信息可以方便调试。 在使用gcc而不是ld做链接的情况下,_start要改为main,因为gcc只认main。 -g 这行必须加不然不能调试,报 Single stepping until exit from function printf, which has no line number information. -fno-pie -no-pie 不加也会报错。 /usr/bin/ld: /tmp/ccbS29lq.o: warning: relocation in read-only section `.text’ /usr/bin/ld: warning: creating DT_TEXTREL in a PIE
但是这个编译存在一些小问题: 1.必须使用main而不能使用_start 2.-o后面跟的可执行程序名 必须和.s文件前面部分的名字一样。这个非常的奇怪。导致gdbinit文件失效。 因为gdbinit文件里面有一个file命令,必须指定程序名字,通常情况下,这个名字是写成固定的例如run.exe或者program等名字,但是因为第2个问题的原因,这个名字就不能固定了。导致gdbinit基本就没法用了。 所以万不得已,不要用gcc这种方式,还是ld的方式比较好。 后面再添加ld的方法…
还有一个问题是每次都必须要编译成32位。因为默认是64位的,在gdb的时候,寄存器什么的都会不一样。这样就不能和书本统一了。
这种方式适合一般情况下:
as -32 -gstabs -o movtest1.o movtest1.s ld -m elf_i386 -o program movtest1.o
|