> [TOC] # x86のレジスター ## 汎用レジスタ #### EAX 関数の戻り値や演算などの結果がよく格納される。 #### ECX #### EDX #### EBX #### ESP 一時的にデータを保存できるスタックのトップのアドレスが格納されている。 スタックにはpush命令やpop命令、mov命令などでデータを格納することも可能。 #### EBP スタックのベースのアドレスが格納されている。 #### ESI #### EDI ## 汎用レジスタのアクセス方法 #### 32ビット EAX、ECX、EDX、EBX ##### 使用例 ###### Assembly ``` mov eax,0x11223344 mov a,eax ``` ###### C言語 ``` eax = 0x11223344; a = eax; ``` #### 16ビット AX、CX、DX、BX ##### 使用例 ###### Assembly ``` mov eax,0x11223344 mov a,ax ``` ###### C言語 ``` eax = 0x11223344; a = eax & 0xffff; // a = 0x3344 ``` #### 8ビット(下位) AL、CL、DL、BL ##### 使用例 ###### Assembly ``` mov eax,0x11223344 mov a,al ``` ###### C言語 ``` eax = 0x11223344; a = eax & 0xff; // a = 0x44 ``` #### 8ビット(上位) AH、CH、DH、BH ##### 使用例 ###### Assembly ``` mov eax,0x11223344 mov a,al ``` ###### C言語 ``` eax = 0x11223344; a = (eax >> 8) & 0xff; // a = 0x33 ``` # x86の呼出規約 ### call命令 callを使用して関数を呼び出します。 call時には戻り先(callの後に実行される命令)のアドレスがスタックに格納されます。このアドレスは基本的にret命令によってEIPが設定されます。 ##### Assembly ``` push size //count push msg //buf push 1 //fd call write section .data msg db 'seccamp', 0xa size equ $ - msg ``` ##### C言語 ``` ssize_t write(int fd, const void *buf, size_t count); char msg[] = "seccamp"; write(1,msg,sizeof(msg)); ``` ### ret命令 retを使用してスタックから戻り先のアドレスを取得し、EIPに設定します。 ##### Assembly ``` mov eax,0 ret ``` ##### C言語 ``` return 0; ``` # x86のopcode(命令コード)一部 ### PUSH/POP #### PUSH ##### PUSH実行前のスタックの状態 ``` --------------------- | 0x11223344 | 0xffffff48 <- ESP |---------------------| | 0x11223344 | 0xffffff4c |---------------------| | 0x11223344 | 0xffffff50 |---------------------| | 0x11223344 | 0xffffff54 |---------------------| ``` ##### PUSH実行後のスタックの状態 ###### Assembly ``` mov eax,0x66774422 push eax ``` ``` --------------------- | 0x66774422 | 0xffffff44 <- ESP |---------------------| | 0x11223344 | 0xffffff48 |---------------------| | 0x11223344 | 0xffffff4c |---------------------| | 0x11223344 | 0xffffff50 |---------------------| | 0x11223344 | 0xffffff54 |---------------------| ``` #### POP ##### POP実行前のスタックの状態 ``` --------------------- | 0x77553322 | 0xffffff48 <- ESP |---------------------| | 0x11223344 | 0xffffff4c |---------------------| | 0x11223344 | 0xffffff50 |---------------------| | 0x11223344 | 0xffffff54 |---------------------| ``` ##### POP実行後のスタックの状態 ###### Assembly ``` pop eax ret // eax = 0x77553322 ``` ``` |---------------------| | 0x11223344 | 0xffffff4c <- ESP |---------------------| | 0x11223344 | 0xffffff50 |---------------------| | 0x11223344 | 0xffffff54 |---------------------| ``` ### データ転送(mov) ##### Assembly ``` mov b,0x00000000 mov a,b push 10 call malloc mov c,eax mov [c],3 mov b,[c] mov eax,b ret //b = 3 ``` ##### C言語 ``` b = 0x00000000; a = b; *c = malloc(10); *(int *)c = 3; b = *(int *)c; return b;// b = 3 ``` ### データ交換(xchg) ##### Assembly ``` xchg a,b ``` ##### C言語 ``` tmp = a; a = b; b = tmp; ``` ### アドレス計算(lea) ##### Assembly ``` lea a,[b+1] ``` ##### C言語 ``` a = b+1; ``` ### 加算(add) ##### Assembly ``` add b,0x11111111 add a,b ``` ##### C言語 ``` b = b + 0x11111111 & 0xffffffff; a = a + b & 0xffffffff; ``` ### 減算(sub) ##### Assembly ``` sub b,0x11111111 sub a,b ``` ##### C言語 ``` b = b - 0x11111111; a = a - b; ``` ### 乗算(mul) ##### Assembly ``` mov eax,0x99999999 mul b ``` ##### C言語 ``` b * 0x99999999; ``` ### 除算(div) ##### Assembly ``` mov eax,0x99999999 div b ``` ##### C言語 ``` b / 0x99999999; ``` ### インクリメント(inc) ##### Assembly ``` inc a ``` ##### C言語 ``` a++; ``` ### デクリメント(dec) ##### Assembly ``` dec a ``` ##### C言語 ``` a--; ``` ### 排他的論理和(xor) ##### Assembly ``` sub b,0x11111111 sub a,b ``` ##### C言語 ``` b = b - 0x11111111; a = a - b; ``` ### 論理積(and) ##### Assembly ``` and a,b ``` ##### C言語 ``` a = a && b; ``` ### 論理和(or) ##### Assembly ``` or a,b ``` ##### C言語 ``` a = a || b; ``` ### 否定(not) ##### Assembly ``` not b ``` ##### C言語 ``` b = !b; ``` ### 算術シフト(sal/sar) ##### Assembly ``` mov a,1 sal a,4 ``` ##### C言語 ``` a = 1; a = a * 16 ``` ### ビットシフト(shl/shr) ##### Assembly ``` mov a,1 shl a,3 ``` ##### C言語 ``` a = 1; a = a << 3 ``` ### 比較 #### test ##### Assembly ``` mov a,0 test a,a jnz goto mov a,1 goto: ret // a = 1 ``` ##### C言語 ``` a = 0; if(a == 0){ a = 1; } return a; // a = 1 ``` #### cmp ##### Assembly ``` mov a,0 cmp a,0 jnz goto mov a,1 goto: ret // a = 1 ``` ##### C言語 ``` a = 0; if(a == 0){ a = 1; } return a; // a = 1 ``` ### 分岐 分岐の命令では、基本的には以下の条件が適用される。 ・命令にNがついた場合条件を否定(not) ・命令にEがついた場合同等(equal) #### jz(ゼロである場合) #### jmp(無条件) #### JB(対象より下の場合) #### JL(対象より小さい場合) #### JG(対象より大きい場合) #### ja(対象より上の場合)