- 入栈和出栈指令
- 移动指令
移动指令
mov S D
movb
movw
movl
-
movq
当源操作数是常数时,这个常数必须是32位的补码进行表示的,而且移动时将会进行64位的符号拓展; -
movabsq
源操作数可以是任意的64位常数值,有符号的或者无符号的;目标操作数必须是寄存器类型;
规定
- 源操作数的值可以是常数值、寄存器类型、内存引用类型;
- 目标操作数可以是寄存器类型、内存引用类型,不能是常数值;
- 源操作数和目标操作数不能同时都是内存引用类型,即从一个内存位置复制一个值到另一个内存位置需要两个指令:首先,将源值加载进某个寄存器,然后将这个寄存器的值写入到目标内存地址处;
移动指令的5种可能的源操作数跟目标操作数组合
常数, 寄存器
常数, 内存引用
寄存器, 寄存器
寄存器, 内存引用
内存引用, 寄存器
例外
当
movl
指令的目标操作数是寄存器类型时,会将寄存器的高4个字节位全设置为0
举例
-
mov
指令的副作用
-
movb
字节移动指令的副作用
3.2 熟悉下移动指令
movl %eax, (%rsp) #32->64,小到大,类型由小丁;
movw (%rax), %dx #64->32,大到小,类型由小定;
movb $0xFF, %bl #8->8
movb (%rsp, %rdx, 4), %dl #64->8,大到小,类型由小定;
movq (%rdx), %rax #64->64
movw %dx, (%rax) #16->64,小到大,类型由小定
3.3 指出下列移动指令中的错误
movb $0xF, (%ebx) #8->32,%ebx不能作为地址寄存器;
movl %rax, (%rsp) #64->64,movl改为movq;
movw (%rax),4(%rsp) #64->64,不能两个操作数都是内存引用类型;
movb %al,%sl # %sl寄存器不存在
movq %rax,$0x123 #常数不能作为目的操作数;
movl %eax,%dx #32->16,movl改为movw;
movb %si, 8(%rbp) #16->64,movb改为movw;
- 4 Assume variables
sp
anddp
are declared with types
src_t *sp;
dest_t *dp;
where src_t
and dest_t
are data types declared with typedef
. We wish to use the appropriate pair of data movement instructions to implement the operation
*dp = (dest_t) *sp;
Assume that the values of sp
and dp
are stored in registers %rdi
and %rsi
, respectively. For each entry in the table, show the two instructions that implement the specified data movement.
The first instruction in the sequence should read from memory, do the appropriate conversion, and set the appropriate portion of register %rax
. The second instruction should then write the appropriate portion of %rax
to memory. In both cases, the portions may be %rax
, %eax
, %ax
, or %al
, and they may differ from one another.
Recall that when performing a cast that involves both a size change and a change of “signedness” in C, the operation should change the size first.
1. long->long # 64->64
movq (%rdi), %rax
movq rax%, (%rsi)
2. char->int #有符号8->有符号32,有符号拓展
movsbl (%rdi), %eax
movl %eax, (%rsi)
3. char->unsigned #有符号8->无符号32,有符号拓展
movsbl (%rdi), %eax
movl %eax, (%rsi)
4. unsigned char->long #无符号8->有符号64,无符号拓展
mobzbq (%rdi), %rax
movl %rax, (%rsi)
5. int->char #有符号32->有符号8,截断处理
movl (%rdi), %eax
movb %al, (%rsi)
6. unsigned->unsigned char #无符号32->无符号8,截断处理
movl (%rdi), %eax
movb %al, (%rsi)
7. char->short #有符号8->有符号16
movsbw (%rdi), %ax
movw %ax, (%rsi)
3.5 You are given the following information. A function with prototype
void decode1(long *xp, long *yp, long *zp);
# xp in %rdi, yp in %rsi, zp in %rdx
is compiled into assembly code, yielding the following:
decode1:
movq (%rdi), %r8
movq (%rsi), %rcx
movq (%rdx), %rax
movq %r8, (%rsi)
movq %rcx, (%rdx)
movq %rax, (%rdi)
ret
Parameters xp
, yp
, and zp
are stored in registers %rdi
, %rsi
, and %rdx
, respectively.
Write C code for decode1
that will have an effect equivalent to the assembly code shown.
解答:
void decode1(long *xp, long *yp, long *zp) {
long x = *xp;
long y = *yp;
long z = *zp;
*yp = x;
*zp = y;
*xp = z;
return z;
}
入栈和出栈指令
pushq S
popq D
入栈指令
pushq %rbp
等价于
subq $8, %rsp
movq %rbp, (%rsp)
出栈指令
popq %rax
等价于
movq (%rsp), %rax
addq $8, %rsp