64位汇编,关于寄存器的坑

; ------------------------------------------------------------------------------
; 64位模式下,立即操作数规范↓↓↓↓↓↓:

; 无论是32位、16位还是8位立即操作数传入rax,高位全都补0.
; 注意:立即操作数即使是负数也是补0,无符号扩展,只是单纯地补0.

; 实验注:
; mov rax, 12345678h -> rax = 0000000012345678h
; mov rax, 9876h     -> rax = 0000000000009876h 注意这和32位约定不同!不会保留eax的高16位!
; 记住只要出现 mov 'reg64', '立即数' 格式, 前面都是无脑补0!

; 64位模式下,立即操作数规范↑↑↑↑↑↑
; ------------------------------------------------------------------------------


; ------------------------------------------------------------------------------
; 64位模式下,内存操作数规范↓↓↓↓↓↓:

; 传递一个32位的内存操作数到eax(注意不是rax,是在64位环境下的eax),那么rax高位全自动补0.
; 但是如果向eax传递的是16位或者8位内存操作数,不影响rax的高48或56位.

; 64位模式下,内存操作数规范↑↑↑↑↑↑
; ------------------------------------------------------------------------------


; ------------------------------------------------------------------------------
; 64位模式下,寄存器操作数规范↓↓↓↓↓↓:

; 无法直接使用mov 'reg64', 'reg32'方法传递寄存器数值
; (mov rax, eax; mov rax, ebx等试图向64位寄存器传递32位寄存器数值的语句都是非法语句.)
; movsxd指令可以使用movsxd 'reg64', 'reg32'方法传递寄存器数值,但是这是带符号扩展的.
; 实验注:
; 1)在64位平台rax已经被赋值的情况下,如果改变eax(32),那么会将原来的rax的高32位清空;
; 2)但在64位平台rax已经被赋值的情况下,如果对ax(16)或al(8)进行赋值,那么会保留原来的rax的高48位或56位!
; *)就32位特殊!!务必记住!!!
; 示例代码1:
; mov rax, 0ABCDEDAC12345678h -> rax = 0xABCDEDAC12345678
; mov eax, 66666666h          -> rax = 0x0000000066666666   =>注意:由于eax是32位寄存器,就32位特殊,要清零!
; mov rax, 0ABCDEDAC12345678h -> rax = 0xABCDEDAC12345678
; mov ax,  1234h              -> rax = 0xABCDEDAC12341234   =>注意:因为ax是16位寄存器,不影响rax的高48位
; mov rax, 0ABCDEDAC12345678h -> rax = 0xABCDEDAC12345678
; mov al,  0FFh               -> rax = 0xABCDEDAC123456FF   =>注意:因为al是8位的寄存器,不影响rax的高56位
; 示例代码2:
; mov rax, 0ABCDABCD12345678h -> rax = 0xABCDABCD12345678h
; mov al, 0FFh                -> rax = 0xABCDABCD123456FFh
; add al, 1                   -> rax = 0xABCDABCD12345600h
; mov al, 0FFh                -> rax = 0xABCDABCD123456FFh
; add rax, 1                  -> rax = 0xABCDABCD12345700h
; mov al, 0FFh                -> rax = 0xABCDACBD123457FFh
; add eax, 1                  -> RAX = 0x0000000012345800H    =>注意:只要是在64位环境下对32位寄存器改动,那
;                                                              么其对应的64位寄存器高位一定会清零
; 64位模式下,寄存器操作数规范↑↑↑↑↑↑
; ------------------------------------------------------------------------------


; ------------------------------------------------------------------------------
; 其他主题↓↓↓↓↓↓:

; LOOP指令使用rcx计数;
; OFFSET产生64位地址,必须使用64位寄存器存储;
; CALL指令使得rsp减去8,因为地址是64位的(rsp每减去1,栈顶扩充一个字节,等价于8个二进制存储位);
; CALL指令在32位规范下esp减去4,因为地址是32位的,32位占有8个字节.
; 关于方括号问题
; 1)源操作数(就是后面那个操作数)是内存
; lea, mov指令对于内存操作数是否加括号没有任何影响
; 示例代码3:
; 已经定义val DWORD 12345678h
; lea eax, [val] -> eax = &val        => &表示val的地址
; lea eax, val   -> eax = &val
; mov eax, [val] -> eax = 0x12345678h 
; mov eax, val   -> eax = 0x12345678h =>结果完全一样
; 2)源操作数是寄存器
;    ①.lea指令.
;        lea指令不支持形如 lea 'reg', 'reg' 的形式(比如lea esi, eax是非法表达式)
;        lea指令支持形如 lea 'reg', '[reg]' 的形式(比如lea esi, [eax]是合法表达式)
;        lea eax, [esi] 取出esi寄存器对应的值的地址(通常这个表达式可以等价于mov eax, esi)
;    ②.mov指令.
;        mov eax, [esi] eax保存esi寄存器指向的值
;        mov eax, esi   eax直接保存esi的原始值
;
; 综上,方括号问题对于《内存变量》没有任何影响,无论是lea指令还是mov指令;
; 但是对于《寄存器变量》,[reg]表示此寄存器所指向的内容,而reg本身就代表其自身的值。

; 其他主题↑↑↑↑↑↑
; ------------------------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值