我的逆向工程之路 - 汇编基础

寄存器、内存、和栈

  1. 寄存器:
  CPU 自带的变量。数量有限。速度最快。存放的是全局变量。
  如果数量较多,就需要放到内存中。
  一些寄存器:   
       CR0, CR2, CR3  (控制寄存器) (如:CR0的作用是切换实模式和保护模式)
       D0, D1, D2, D3, D6和D7  (调试寄存器)(作为调试器的硬件支持来设置条件断点)
       TR3, TR4, TR5, TR6 和TR? (测试寄存器)(于某些条件测试)
       CS  代码段
       DS  数据段
       ES  附加段
       SS  堆栈段
  1. 内存:
存放的也是全局变量。
  1. 栈:
  存放局部本地变量。
  也是一个内存区域,只有拥有栈的特点: 先进后出。ARM的栈是满递减,栈低内存地址最小。

实用寄存器 详解:

 SP  Stack Pointer 保存栈的栈底地址,称为栈地址。
     实际操作中,栈地址会不断变化,但是一块代码里面 栈地址是不变的。
 PC  Program Counter 存放下一条指令的地址
     一般情况下,处理器执行完一条指令后,将PC加1.顺序执行
 LR  Link Register 连接寄存器,
     一是用来保存子程序返回地址;
     二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2)
     因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行
 PSR Program Status Register 程序状态寄存器。
     程序的条件判断准则(flag), 如:结果是否为0 | 负数 | 有进位 | 溢出

指令解读

预备知识: { }表示可选项, [ ]表示间接寻址, #立即数直接寻址,@间接寻址

  1. 数据操作指令:

基本格式: op { cond }{ s } Rd, Rn, Op2

  op 指令, cond条件, s设置flag, op2可以是寄存器、被移位的寄存器或立即数。
(如:ADD R0,R1,#5 ;R0=R1+5   #5为立即数)

  cond条件: 
EQ    结果为0      EQual to 0 
NE    结果不为0     Not Equal to 0 
CS    有进位或借位   Carry Set 
HS    同CS         CS unsigned Higher or Same 
CC    没有进位或借位 Carry clear 
LO    同CC         unsigned LOwer 
MI    结果小于0 MInus 
PL    结果大于0 PLus 
VS    溢出   oVerflow Set 
VC    无溢出  oVerflow Clear 
HI    无符号比较大于         unsigned HIgher 
LS    无符号比较小于等于      unsigned Lower or Same  
GE    有符号比较大于等于      signed Greater than or Equal 
LT    有符号比较小于    signed Less Than 
GT    有符号比较大于    signed Greater Than 
LE    有符号比较小于等于 signed Less than or Equal 
AL    无条件 Always,默认

  s的四种flag:
N  negative 负数: 结果小于0 则置1,否则置0;
Z  zero 零:       结果是0则置1, 否则置0;
C  carry 位移:     产生进位则置1,否则0,减操作则产生借位则置0,否则置1...
V  overflow 溢出:  操作有导致溢出,则置1, 否则置0。(有符号数运算结果,无符号数溢出用C)

算术操作:

ADD R0, R1, R2;    R0=R1+R2
ADC R0, R1, R2;    R0=R1+R2 + C(carry)
SUB R0, R1, R2;    R0=R1-R2 
SBC R0, R1, R2;    R0=R1-R2 - !C 
RSB R0, R1, R2;    R0=R2-R1 
RSC R0, R1, R2;    R0=R2-R1 - !C

逻辑操作:

AND R0, R1, R2;    R0 = R1 & R2
ORR R0, R1, R2;    R0 = R1 | R2
EOR R0, R1, R2;    R0 = R1 ^ R2 
BIC R0, R1, R2;    R0 = R1 &~ R2
MOV R0, R1;        R0 = R1 
MVN R0, R1;        R0= ~ R1

位移操作:  (如:ADD R0,R1,R2,LSL#5 ;R0=R1+R2左移5位)
LSL 逻辑左移,
LSR 逻辑右移,
ASR 算术右移,
ROR 循环右移

比较操作:

CMP R1, R2   执行  R1 - R2,并依结果设置flag,
CMN R1, R2   执行  R1 + R2,并依结果设置flag,
TST R1, R2   执行  R1 & R2,并依结果设置flag, 
TEQ R1, R2   执行  R1 ^ R2,并依结果设置flag,

乘法操作:

MUL R4, R3, R2;       R4 = R3 * R2
MLA R4, R3, R2, R1;   R4 = R3 * R2 + R1
  1. 内存操作指令:

基本格式:

op {cond} {type} Rd, [Rn, Op2]
  Rn 是基地址寄存器,用于存放基地址。cond 和上面的一样。

  type的四种数据类型 (不指定type,则是默认数据类型word)
  B (unsigned Byte)     无符号byte,执行时扩展到32位,以0填充
  SB (signed Byte)      有符号byte,仅用于LDR指令,执行时扩展到32位,以符号位填充
  H (unsigned Halfword) 无符号halfword,执行时扩展到32位,以0填充
  SH (signed Halfword)  有符号halfword,仅用于LDR指令,执行时扩展到32位,以符号位填充

ARM内存操作基础指令只有两个:
LDR: (Load Register)将数据从内存中读出来,存到寄存器中。

  LDR Rt, [Rn {, #offset}];   Rt = *(Rn {+offset}),  { }代表可选
  LDR Rt, [Rn, #offset]!;     Rt = *(Rn + offset);  Rn = Rn + offset
  LDR Rt, [Rn], #offset;      Rt = *Rn; Rn = Rn + offset

STR: (Store Register)将数据从寄存器中读出来,存到内存中。

  STR Rt, [Rn {, #offset}];  *(Rn {+offset}) = Rt
  STR Rt, [Rn, #offset]!;    *(Rn {+offset}) = Rt; Rn = Rn + offset
  STR Rt, [Rn], #offset;     *Rn = Rt; Rn = Rn + offset

其变种:LDRD 和 STRD 还可以操作双字(Doubleword),即一次操作两个寄存器
基本格式:

op {cond} Rt, Rt2, [Rn {, #offset}]

用法和上面的类似:

  LDRD R4, R5, [R9, #offset];     R4 = *(R9 + offset); R5 = *(R9 + offset +4)

  STRD R4, R5, [R9, #offset];     *(R9 + offset) = R4; *(R9 + offset + 4) = R5

除了基础指令,还有两个块传输指令(一次操作多个寄存器):
基本格式:

op {cond}{mode} Rd {!}, reglist
Rd 是基址寄存器, !指定Rd变化后的值是否写会Rd, reglist是一系列寄存器 
(如:{R4-R6, R8} 就表示R4,R5,R6, R8寄存器) "{ }"  "-"  "," 

  mode 指定Rd的4种变化规律:
IA  increment after,  每次传输后增加Rd的值;
IB  increment before, 每次传输前增加Rd的值;
DA  decrement after, 每次传输后减少Rd的值;
DB decrement before, 每次传输前减少Rd的值。

  LDM  Load multiple   Rd开始连续的内存数据存入reglist中。
  STM  Store multiple  吧reglist中的值存入 从Rd开始的连续地址中。
  
  LDMIA R0, {R4 - R6};   表示吧R0开始的内存里面的值 依次存入寄存器中。

可以发现 LDM、STM 和 LDR、STR 的格式是相反的。
LDM 和 STM 是: op 内存地址 寄存器
LDR 和 STR 是: op 寄存器 内存地址

  1. 分支指令:

分为无条件分支 和 条件分支两种。
无条件分支:

B   Label;   PC = Label, go to 的意思,直接跳到Label处执行。
BL  Label;   LR = PC - 4; PC = Label
BLX Label;   Label 后面的指令必须为THUMB指令  LR = PC - 4; PC = Label;
BX  Rd;      PC = Rd 并切换指令集(THUMB 或 ARM)

条件分支:

在该指令前,会有一条数据操作指令来设置flag,分支指令根据flag的值来决定代码走向
CMP  R0, 0;  (比较指令)如果R0 == 0 则 Z = 1, 否则 Z = 0
BNE  Label;  (B  + NE 如下)Z == 0 则跳到Label处执行

  cond flag
EQ   Z=1
NE   Z=0
CS   C=1
HS   C=1
CC   C=0
LO   C=0
MI   N=1
PL   N=0
VS   V=1
VC   V=0
HI   C=1&Z=0 LS C=0|Z=1 GE N=V
LT   N!=V
GT   Z=0&N=V LE Z=1|N!=V
  1. THUMB指令:

THUMB 指令是ARM指令的子集,均为16位,在16位的数据总线上的传输效率更高,比ARM指令更节省空间。
特点:

  1. 除了B指令外,所有的指令均无法条件执行。
  2. 桶式位移无法结合其他指令执行。
  3. 大多数指令只能使用R0 ~ R7 这八个寄存器。
      (例外:ADD、MOV、CMP 可以将 R8~R15 作为操作数使用。
            LDR、STR 可以使用 PC 或 SP 寄存器
            PUSH 可以使用 LR     
            POP 可以使用 PC
            BX 可以使用所有寄存器)
  4. 指令数量减少,如:乘法中只有MUL保留,其他都被精简了。
  5. 所有的指令默认附带s,即所有的THUMB指令都会设置flag。
  6. 立即数 和 第二操作数使用受限。 除了位移指令、ADD、SUB 其他指令形式都是 "op Rd, Rm"
  7. 不支持数据回写,即{!} 不可用了。

后记:

  1. 传递参数和返回值:
    函数的前四个参数 放在 R0 ~ R3 寄存器中,其他参数放在栈中。 返回值放在R0中。
  2. 特殊用途寄存器:
R0 ~ R3   传递参数与返回值;
R7     帧指针,指向母函数与被调用子函数在栈中的交界;
R9     在iOS 3.0 以前被系统保留;
R12    内部过程调用寄存器,dynamic linker 会用到它;
R13    SP寄存器;
R14    LR寄存器,保存返回值;
R15    PC寄存器
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容