汇编语言学习

x86-64位寄存器(16个)

rax:存放保存函数返回值
rbx:被调用者保存
rdi rsi rdx rcx 对应第1、2、3、4个参数
rsp:栈指针,存放栈帧的栈顶的偏移地址
r8 r9对应第5、6个参数

汇编

寻址

立即数寻址$Imm Imm(立即数)
寄存器寻址%ra R[ra] (寄存器)
绝对寻址Imm M[Imm] (存储器)
间接寻址(%ra)M[R[[ra]]

例题

下面有一点地址或寄存器的值,写出操作数的值
地址 值 寄存器 值
0x100 0xFF rax 0x100
0x104 0xab rcx 0x1
0x108 0x13 rdx 0x3
0x10C 0x11
操作数 值
rax 0x100(寄存器)
0x104 0xab(绝对寻址)
$0x108 0x108(立即数寻址)
(%rax) 0xFF(间接寻址)

指令

两种汇编模式
ATT汇编movq movb
普通汇编 mov rax,rbx=movq %rbx,%rax (ATT):把rbx的值赋给rax

mov

mov 数据传送指令 将数据从一个位置复制到另一个位置的指令
mov 寄存器/立即数 操作数用来指向一个执行所要使用源数据的值,放置结果的目的位置,mov 源操作数的值是一个立即数,值存放在内存或者寄存器中 目的操作数一个寄存器或者是一个内存地址。

单位:1字节 = 8bit 1字 = 8字节 = 64bit

movb 一个字节 (这个字代表双字节的意思,与上边的字不一样)
movw 一个字
movl 双字(寄存器的高四字节设置成0)
movq 四字
movabsq I,R R<-I 传送的是绝对的四字 目的操作数只能是寄存器

movl $0x4050,%eax 4bytes 立即数–寄存器
movw %bp,%sp 2bytes 寄存器–寄存器
movb (%rdi,%rcx),%al 1bytes 内存–寄存器
movb $-17,(%rsp) 1bytes 立即数–内存
movq %rax,-12(%rbp) 8bytes 寄存器–内存l

例题1

movabsq $0x0011223344556677 , %rax = 0011223344556677
( rax包含了eax eax包含了ax ax包含了al)
-1的16进制是0xFFFFFFFFFFFFFF,第一步结束后每一步rax的值是多少
movb $-1 ,%al , %rax = 00112233445566FF F = 1111
movw $-1 , %ax , %rax = 001122334455FFFF
movl $-1 , %eax , %rax = 00000000FFFFFFFF
movq $-1 ,%rax , %rax = FFFFFFFFFFFFFFFF

例题2

把下列汇编代码用c语言表示 (rax一直保存的是返回值)

decode1:
    movq (%rdi) , %r8
    movq (%rsi) , %rcx
    movq (%rdx) , %rax
    movq %r8    , (%rsi)
    movq %rcx   , (%rdx)
    movq %rax ,   (%rdx)      
    ret 

c语言

long decode1(long *xp,long *yp,long *zp){
     long x = *xp;
     long y = *yp;
     long z = *zp;
     *yp = x;
     *zp = y;
     *xp = z;
     return z;
 }    
     
push和pop

push压入栈 pop弹出栈(pop弹出的值一直是一个最近压入栈的数据且仍在栈中)
由于栈是由大到小增长的,所以栈顶永远是地址最低的 %rsp保存着栈顶的元素
pushq popq 将四字压入栈中 将四字弹出栈
pushq %rbp = subq $8,%rsp movq %rbp,(%rsp) (rsp地址减8)
popq %rax <==> movq (%rsp),(%rax) addq $8,%rsp (rsp地址加8)
pop之后,值不会被删除,除非有一个新的值覆盖了原先的值

算数和逻辑操作
leaq  --> 加载有效地址 
inc --> 加一 
dec --> 减一 
neg --> 取负 
not --> 取补 
add --> 加 
sub --> 减 
imul --> 乘 
xor --> 异或 
or --> 或 
and --> 与 
sal --> 算数左移 
 sar --> 算数右移 
 shl -->逻辑左移
shr --> 逻辑右移
1.加载地址

movq的一种变形 从内存读数据到寄存器 但是没有引用内存 不是单纯的读数据,而是将有效地址加载到目的操作数 描述简单的算数操作

例题

rdi = x
leaq 7(%rdi,%rdi,4),%rax == 将rax的值设置为5x+7

2.一元操作和二元操作

只有一个操作数的是一元操作,既是源操作数也是目的操作数
地址 值 寄存器 值
0x100 0xFF rax 0x100
0x108 0xAB rcx 0x1
0x118 0x11 rdx 0x3
subq %rax,%rdx rdx = rdx -rax
addq %rcx , (%rax) ;更新的其实是一个内存位置 位置为0x100
imulq $16,(%rax,%rdx,8) ;更新的内存位置是0x118,值对应的是0x11*16=0x110
他们的目的和最终值写出来
imulq 有符号乘法 一个操作数 这个指令要求就是必须两个数都在寄存器rax中 把高64位存放在rdx,低64位存放在rax里面
salq $4,%rax(左移4位,扩大了2的4次方倍)

控制操作

t = a + b
无符号溢出 CF (条件码)
t==0 ZF
t < 0 SF
(a<0&&b<0) && (t<0 != a <0) 有符号溢出 OF
leaq 不会改变任何条件码 xor 会将进位标志和溢出位标志设置成0
cmpb 比较字节 cmpw 比较字 test 测试
cmp rsi,rdi
cmp根据两个比较数的差来设置条件码 (除了不更新寄存器以外,和sub操作是一样的 test也是除了不更新寄存器以外,和 and 操作是一样的)
testq %rax,%rax 检查rax是负数还是正数还是0
set指令设置条件码
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值