为什么要写这个呢?因为有时候要看64位的汇编代码,如果不知道这些常识的话,看64位汇编代码会很困难的。 32位和16位就不提了,因为大学本科的教材中都有。下面补充一点64位的。 01、寄存器的长度发生了变化,相应的名称也变化了。比如:EAX,EBX,ECX,EDX 这些仍然存在,只是扩展成了新的64位寄存器RAX,RBX,RCX,RDX等。 02、新增了很多64位寄存器。例如:R8,R9,R10,R11,R12,R13,R14,R15。 03、调用方式发生了变化。第1个参数到第4个参数,用 RCX,RDX,R8,R9 传递,从第5个参数开始,用堆栈来传递。 04、有一个奇特的现象:被调用的函数会把传来的参数暂存到主调函数的堆栈中。因此,主调函数在调用一个函数之前,会在堆栈中多留出一些空间。 下面还是拿之前的汇编代码来讲解: mov [rsp+10h], rdx ;SystemTable mov [rsp+8], rcx ;句柄ImageHandle sub rsp, 28h mov rax, [rsp+28h+10h] mov rax, [rax+40h] ;获取ConOut lea rdx, [szOK] ;要显示的字符串 mov rcx, [rsp+28h+10h] mov rcx, [rcx+40h] ;获取ConOut call QWORD[rax+8] ;调用OutputString xor eax, eax add rsp, 28h retn 第1行和第2行是把传来的参数 rdx,rcx 暂存到主调函数的堆栈里。 第4行又到主调函数的堆栈中,取出刚才暂存的值。 为什么第4行不直接用 rdx 呢?多此一举干什么呢?本人猜测原因可能是:编译器把传来的参数,也就是 rdx,rcx往主调函数的堆栈里存起来。这样 rdx,rcx 就可以当临时变量使用了,也就是说, rdx,rcx可以放其它的值,等到想用之前的值,就到主调函数的堆栈里去取出来。 最后补充一点:为什么要写成[rsp+28h+10h]?不写成[rsp+38h]?原因是:为了方便理解程序。 |
|