64位Linux默认使用小内存模型,它将所有代码和静态数据置于2GB地址限制之下.这可确保您可以使用32位绝对地址.较旧版本的gcc使用静态数组的32位绝对地址,以便为相对地址计算保存额外的指令.但是,这不再有效.如果我尝试在汇编中创建一个32位的绝对地址,我会收到链接器错误:"在创建共享对象时,不能使用".data"重定位R_X86_64_32S;使用-fPIC重新编译".当然,此错误消息具有误导性,因为我没有创建共享对象,-fPIC也没有帮助.到目前为止我发现的是:gcc版本4.8.5对静态数组使用32位绝对地址,gcc版本6.3.0不使用.版本5可能也没有.binutils 2.24中的链接器允许32位绝对地址,而2.28则不允许.
这种变化的后果是必须重新编译旧库并破坏传统汇编代码.
现在我想问一下:这个改变是什么时候做的?它在某处记录了吗?是否有一个链接器选项,使其接受32位绝对地址?
我在Linux上学习asm(noobuntu 10.04)我得到了以下代码:http://asm.sourceforge.net/intro/hello.html
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
Run Code Online (Sandbox Code Playgroud)
这是一个简单的问候世界.Linux +上的运行直接调用内核(显然).有谁能解释一下这里到底发生了什么?我认为它读取eax&ebx处理器寄存器和ecx,edx数据中的整数,并在调用内核时定义系统调用.如果是这样,当调用int 0x80时,不同的整数组合是否定义了不同的系统调用?
我对man页面不太满意,但已经阅读了我能找到的每一个相关的页面,是否有任何man page告诉我哪些组合定义了什么系统调用?
任何帮助表示赞赏.逐行解释将是惊人的... - 谢谢提前杰里米
这是一个以前没有发生过的问题.我很确信这可能是我的包装回购的一个问题(我最近重新安装了我的Arch系统,而这刚刚开始发生).
我在x86_64中写了一个小小的hello世界:
.data
str: .asciz "Test"
.text
.globl main
main:
sub $8, %rsp
mov $str, %rdi
call puts
add $8, %rsp
ret
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用GCC进行汇编和链接 - 就像我过去做过很多次一样 - 简单地说:
gcc test.s -o test
然后输出此错误:
/ usr/bin/ld:/tmp/ccAKVV4D.o:在创建共享对象时,不能使用针对`.data'的重定位R_X86_64_32S; 使用-fPIC/usr/bin/ld重新编译:最终链接失败:输出collect2上的不可表示的部分:错误:ld返回1退出状态
这个错误从来没有发生在我身上.我试图通过谷歌搜索相同的错误消息解决问题,但它提出了具体的事情,而我认为这是一个普遍的问题.我已经尝试重新安装base-devel和整个GCC工具链.我不知道我还能做什么(请不要建议使用nasm,这是异端邪说).
我想我错过了一些明显的东西,但是我已经将GCC用于我的装配需求很长一段时间了.