您的位置:首页 > 其它

汇编语言程序设计读书笔记(2)- 相关工具64位系统篇

2013-11-06 18:03 253 查看
汇编语言程序设计一书,在32位系统下应该不会有什么问题,然而在64位系统下,则会有些不一样的地方。有些程序范例还会汇编错误或者执行错误。

博主所用系统为CentOS v6.4 x64。本文主要解决32位的汇编程序如何在64位环境下汇编、连接,而不论述64位汇编语言如何设计。

1. 64位系统下编译32位的C程序

以程序test5.c为例,程序代码很简单,如下:

cpuid2.s# cpuid2.s file
.section .data
output:
.asciz "CPUID is '%s'\n"
.section .bss
.lcomm buffer, 12
.section .text
.globl _start
_start:
nop
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


这个代码的具体实现,后续的章节会介绍。目前只知道是用于输出CPU厂商ID字符串的就行了。

在64位系统下,如果按照书中所述的那样as和ld,会产生错误,如下图:





说是push操作无效。

如果不修改源代码为64位的汇编,要解决这个问题,就需要命令64位系统按照32位的去汇编,as参数是--32, ld参数是-m elf_i386。如下图:





file cpuid2可以看到确实是32位的文件,而且执行也没有问题。这里要特别对ld -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o cpuid2 -L/lib -lc cpuid2.o这行命令进行说明。

-m elf_i386:表示按照elf_i386的模块进行连接,即32位的。

-lc: 因为程序中调用了标准的C库函数printf和exit,因此需要连接C动态库libc.so,所以需要参数-lc来指定连接的库文件,一般而言libxxx.so采用-lxxx的参数。

-L/lib:博主的系统有多个libc.so,包括64位的,32位的,arm结构的,如下图所示,能搜出很多个libc.so。





而/lib/libc.so才是32位x86系统所需要的动态库,所以使用-L/lib来指定库文件的路径,那么-L/lib –lc就指定了连接的是/lib/libc.so。

-dynamic-linker /lib/ld-linux.so.2:用于运行时动态加载libc.so动态库的。否则执行生成的可执行文件时会出错。

3). 64位系统下用gcc汇编32位的汇编程序

还是以上面的cpuid2.s为例,使用gcc -m32的参数进行汇编成32位的系统文件,特别的,这里由于没有main函数,而是用_start做入口点,因此需要使用参数 –nostdlib,如下图:





对gcc -nostdlib -m32 -o cpuid2 cpuid2.s -L/lib -lc进行说明。

-m32:按照32位的编译。

-nostdlib:如果没有这个参数,gcc会连接gnu库的函数,该函数会以_start为进入点,执行一段程序后,跳到main执行,而这个汇编源程序中用_start做进入点,而且没有main,因此,没有这个参数的话,会提示没有main定义以及重复定义_start的错误。加了这个参数后,则不会去连接gnu函数。

综上所述,64位系统下汇编32位汇编程序的做法是:

as --32 –o output_file.o input_file.s

ld –m elf_i386 –dynamic-linker /lib/ld-linux.so.2 –o output_file –L/path –llibname input_file.s

或者

gcc –m32 –nostdlib –o output_file –L/path –llibname input_file.s
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: