Mr.*_*nce 24 assembly x86-64 isr
我正在看一个学校项目中的一些旧代码,并试图在我的笔记本电脑上编译它时遇到了一些问题.它最初是为旧的32位版本的gcc编写的.无论如何,我试图将一些程序集转换为64位兼容代码并遇到一些障碍.
这是原始代码:
pusha
pushl %ds
pushl %es
pushl %fs
pushl %gs
pushl %ss
Run Code Online (Sandbox Code Playgroud)
pusha在64位模式下无效.那么在64位模式下,在x86_64汇编中执行此操作的正确方法是什么?
必须有一个原因,为什么pusha在64位模式下无效,所以我有一种感觉手动推送所有寄存器可能不是一个好主意.
dou*_*536 18
REX在开发64位x86扩展时,AMD需要一些空间来添加前缀的新操作码和一些其他新指令.他们将某些操作码的含义改为新指令.
其中一些说明只是现有说明的简写形式,或者不是必需的.PUSHA是受害者之一.目前尚不清楚他们为什么禁止PUSHA,但似乎并没有重叠任何新的指令操作码.也许它们是未来使用的保留PUSHA和POPA操作码,因为它们完全是冗余的,并且不会更快,并且在代码中不会频繁发生.
的顺序PUSHA是指令编码的顺序:eax,ecx,edx,ebx,esp,ebp,esi,edi.注意它被多余推esp!你需要知道esp找到它推送的数据!
如果是从64位代码转换的PUSHA代码是没有好,无论如何,你需要更新它推新寄存器r8通r15.您还需要保存和恢复一个更大的SSE状态,xmm8直通xmm15.假设你要破坏它们.
如果中断处理程序代码只是转发到C代码的存根,则不需要保存所有寄存器.你可以假设C编译器将生成将保持代码rbx,rbp,rsi,rdi,和r12直通r15.您应该只需要保存和恢复rax,rcx,rdx和r8直通r11.(注:在Linux或其它系统V ABI的平台,编译器会保留rbx,rbp,r12- r15,你可以期望rsi和rdi惨败).
段寄存器在长模式下不保持任何值(如果被中断的线程在32位兼容模式下运行,则必须保留段寄存器,谢谢ughoavgfhw).实际上,他们在长模式下摆脱了大部分细分,但FS仍然保留给操作系统用作线程本地数据的基地址.寄存器值本身并不重要,它的基础FS和GS设置通过MSR 0xC0000100和0xC0000101.假设你不会使用FS你不需要担心它,只要记住C代码访问的任何线程本地数据都可以使用任何随机线程的TLS.请注意这一点,因为C运行时库使用TLS来实现某些功能(例如:strtok通常使用TLS).
将值加载到FS或GS(甚至在用户模式下)将覆盖FSBASE或GSBASEMSR.由于某些操作系统使用GS"处理器本地"存储(它们需要一种方法来指向每个CPU的结构),因此需要将它保留在不会因GS用户模式加载而被破坏的地方.为了解决这个问题,为GSBASE寄存器保留了两个MSR :一个是活动的,一个是隐藏的.在内核模式下,内核GSBASE保存在通常的GSBASEMSR中,而用户模式库则保存在另一个(隐藏的)GSBASEMSR中.当上下文从内核模式切换到用户模式上下文时,以及在保存用户模式上下文和进入内核模式时,上下文切换代码必须执行SWAPGS指令,该指令交换可见和隐藏GSBASEMSR 的值.由于内核GSBASE在用户模式下安全地隐藏在其他MSR中,因此用户模式代码无法GSBASE通过加载值来破坏内核GS.当CPU重新进入内核模式时,上下文保存代码将执行SWAPGS并恢复内核GSBASE.
学习做这种事情的现有代码.例如:
SAVE_ARGS_IRQ):entry_64.SINTR_PUSH):privregs.hIDT_VEC):exception.S(类似于NetBSD中的vector.S)实际上,"手动推送"regs是AMD64的唯一途径,因为PUSHA那里不存在.AMD64在这方面并不是唯一的 - 大多数非x86 CPU确实需要逐个寄存器保存/恢复.
但是,如果仔细检查引用的源代码,您会发现并非所有中断处理程序都需要保存/恢复整个寄存器集,因此存在优化空间.
pusha在64位模式下无效,因为它是冗余的.单独推送每个寄存器正是要做的事情.
嗨,这可能不是正确的方法,但是可以创建像这样的宏
.macro pushaq
push %rax
push %rcx
push %rdx
push %rbx
push %rbp
push %rsi
push %rdi
.endm # pushaq
Run Code Online (Sandbox Code Playgroud)
和
.macro popaq
pop %rdi
pop %rsi
pop %rbp
pop %rbx
pop %rdx
pop %rcx
pop %rax
.endm # popaq
Run Code Online (Sandbox Code Playgroud)
如果需要,最终添加其他 r8-15 寄存器
| 归档时间: |
|
| 查看次数: |
21027 次 |
| 最近记录: |