intel (2018/08/31)
雖然網路上有不少資料,不過想想就當殺時間整理個吧
文章的結尾會放上參考資料(突然覺得在咖啡廳聽Miku的歌有一種衝突爽的感覺)
16 32 64的暫存器基本上主要的暫存器都是以擴充的方式存在
然後你下面看到的 AL/AH就代表是AX的低八位元與高八位元的暫存器,而AX就是EAX低16位的存在
同理 BL/BH/BX 和 CL/CH/CX 都是同樣的存在
雖然每個暫存器都能做任何事,但當初設計他們還是有目的的:
AL/AH/AX/EAX/RAX: Accumulator
[運算用的暫存器,通常function如果有參數的時候也都是先存在這裡面]BL/BH/BX/EBX/RBX: Base index (for use with arrays)
[基底暫存器,通常是用在陣列使用(像是要define第0個位置在哪)]CL/CH/CX/ECX/RCX: Counter (for use with loops and strings)
[計數暫存器,是重複指令(REP)的前綴指令和loop指令的計數器,通常用在迴圈上]DL/DH/DX/EDX/RDX: Extend the precision of the accumulator (e.g. combine 32-bit EAX and EDX for 64-bit integer operations in 32-bit code)
[用來提升(擴充)累加器的的精確度,後面的舉例是擴充EAX的容量,讓32-BIT的系統能做到64-BIT的運算,對岸的文章是說可以拿來當除法運算時放餘數的地方]SI/ESI/RSI: Source index for string operations.
[來源索引暫存器]DI/EDI/RDI: Destination index for string operations.
[目的索引暫存器]
舉個例子來說1
mov eax,ebx
是把ebx的資料放到eax內,那SI就會指向ebx的位置,DI就會指向eax位置
SP/ESP/RSP: Stack pointer for top address of the stack.
[Stack裡面的指標暫存器,用來指向Stack的最上面,每push/pop一個值,SP就會-+2、ESP-+4以此類推]BP/EBP/RBP: Stack base pointer for holding the address of the current stack frame.
[Stack裡面的指標暫存器,總是指向Stack Frame的最下面]
這兩個registers是規劃Stack Frame很重要的兩個registers
Stack是一個倒過來放的空間,最底下的記憶體位置最大,越上面數字會越小
關於Stack的說明可以看看我寫的其他篇文章
- IP/EIP/RIP: Instruction pointer. Holds the program counter, the address of next instruction.
[暫存器會存放下一個CPU指令的記憶體位址,當CPU執行完現在的指令後,從EIP暫存器中讀取下一個指令的記憶體地址,然後繼續執行]
Segment registers:
- CS: Code
- DS: Data
- SS: Stack
- ES: Extra data
- FS: Extra data #2
- GS: Extra data #3
因為Segment registers基本上objdump看不到,所以這邊直接引用一篇我覺得寫得很好的文章
P.S 一開始很疑惑為什麼找X86 CPU的暫存器會有AX、BX、CX這些暫存器,
X86不是=32-BIT嗎?那應該是EAX、EBX、ECX才對啊
仔細查了之後才發現原來我錯了,查了英文wiki對照中文WIKI之後才知道原來
x86是一系列向下相容的指令及架構,基於8086的CPU在1978年被intel提出,x86是intel根據8位元的8080處理器為基底製作出的架構
為什麼會叫x86的原因是8086後繼的CPU(80186, 80286, 80386 and 80486)尾數都有86所以就以x86架構為總稱
所以,基於16-bit的暫存器(AX、BX、CX…)這些並沒有因為32-BIT的緣故而消失了1
2所有16位元的暫存器除了區段暫存器外都擴充為32位元。Intel在暫存器的助記符號上加入「E」來表示(因此擴充的AX變成EAX,SI變成ESI,依此類推)。
因為有更多的暫存器數量、指令、和運算單元,因此機器碼的格式也被擴充。為了提供與先前的架構相容,包含執行碼的區段可以被標示為16或是32位元的指令集。此外,特殊的前置符號也可以用來在16位元的區段包含32位元的指令碼,反之亦然。
同理也可以推到64BIT的暫存器上(不過x64的架構更複雜就是了),這就是為什麼64-BIT的系統能夠執行32-BIT的程式(因為我她媽的就是你的進化版啊!!)
最後引用一下WIKI的文章我就要結束介紹指令集的歷史了(看的很累)1
2
3x86的32位元架構一般又被稱作IA-32,全名為「Intel Architecture, 32-bit」。其64位元架構由AMD率先推出,並被稱為「AMD64」。之後也被Intel採用,被其稱為「Intel 64」。一般也被稱作「x86-64」、「x64」。
值得注意的是,Intel也推出過IA-64架構,雖然名字上與「IA-32」相似,但兩者完全不相容,並不屬於x86指令集架構家族。
參考資料(一些沒貼在內文上的網址):
https://wenku.baidu.com/view/746a9259804d2b160b4ec04d.html
http://finalfrank.pixnet.net/blog/post/22995899
https://en.wikipedia.org/wiki/Stack_register
ARM (update in 2020/11/11)
source:
https://speakerdeck.com/terrynini/ntust
https://speakerdeck.com/terrynini/ais3-firmware-security-analysis
arm 的特性還蠻複雜的,這邊紀錄一下,以 armv7 (32 bits) 搭配 rapple 進行 demo
register
arm 本身有 15 個 registers, 分別為 R0~R15
這 15 個的作用分別為:1
2
3
4
5
6
7r15 (pc) : Program counter (as per the instruction set specification).
r14 (lr): Link register. The BL instruction, used in a subroutine call, stores the return address in this register.
r13 (sp): Stack pointer. The Push/Pop instructions in "Thumb" operating mode use this register only.
r12 (ip): Intra-Procedure-call scratch register.
r11 (sp): Frame pointer. Stack base pointer for holding the address of the current stack frame (optional). Sometime it will be "Local variables".
r4 to r11: Local variables.
r0 to r3: Argument values passed to a subroutine and results returned from a subroutine.
ref: https://en.wikipedia.org/wiki/Calling_convention
介紹完 registers 之後我們來說說 arm 的組語特性
mov r1,#1
mov r1,#0xff
armv7 的所有數字前面都要加一個 #
mvn r2,#0xf = mov r2, (0xffffffff - 0xf)
在 armv8 (aarch64) 的暫存器還多了 movw 和 movt 兩個指令
1 | MOVW 把 16 位立即数放到寄存器的底16位,高16位清0 |
ref: https://blog.csdn.net/dahailantian1/article/details/78584852
ldr/str
只有 ldr 和 str 這兩個指令可以存取記憶體
LDR 的使用格式為1
LDR{條件式}(optional) 暫存器 (distanation), [記憶體位置](source)
STR 的使用格式為1
STR{條件式}(optional) 暫存器 (source), [記憶體位置](distanation)
ldr r0,[sp,#4] = mov r0, [sp+4]
str r2, [sp] = mov [sp], r2
str r2, [sp],#4 = mov [sp], r2 ; add sp, 4
str r2, [sp,#-4]! = sub sp, 4 ; mov [sp], r2 = push r2
ldr r6,[sp],#4 = mov r6, [sp+0x4] ; add sp, 4 = pop r6