汇编学习笔记

#include "test01.h"
int main() {
	//F9增删断点/直接点击左边空位
	//F5执行到下一个断点
	//F10逐行执行不进函数
	//F11逐行执行进入函数
	int a = 20000;
	int* p = &a;
	printf("0x%p\n", p);
	//十进制的20000转成十六进制是4e20,int占四字节空间
	//可以看到连续四个字节是20 4e 00 00 ,显然20在低位,4e在高位,得知win32是小端模式!
	char* cp = (char*)p;
	printf("%02x,%02x,%02x,%02x\n", cp[0], cp[1], cp[2], cp[3]);
	return 0;
	/*
		8086CPU寄存器:
		CS/DS/SS/ES是段寄存器,分别是code segment/data segment/stack segment/extract segment(暂不知有何用)
		AX/BX/CX/DX是通用寄存器,AX可以分成AH与AL,16位(四个16进制数字表示)分成两个8位,溢进后会把进位寄存器置1
		IP与CS搭配使用,IP就是偏移地址,注意CS与IP不能MOV,只可jump 2AE3:3就是跳到2AE*16+3
		SI是源数据指针,DI是目的地址指针,两个都是与DS配合,注意DS必须由寄存器转入
		SP与SS配合,SP就是偏移地址,得到的就是栈地址
		BP是基地址寄存器,一般在访问数组或是有固定偏移量的记录时用于存放基地址,就是说在用到数组时使用
		FR是各种标志位:
		OF overflow flag 溢出标志 操作数超出机器能表示的范围表示溢出,溢出时为1.
		SF sign Flag 符号标志 记录运算结果的符号,结果负时为1.
		ZF zero flag 零标志 运算结果等于0时为1,否则为0.
		CF carry flag 进位标志 最高有效位产生进位时为1,否则为0.
		AF auxiliary carry flag 辅助进位标志 运算时,第3位向第4位产生进位时为1,否则为0.
		PF parity flag 奇偶标志 运算结果操作数位为1的个数为偶数个时为1,否则为0.
		DF direcion flag 方向标志 用于串处理.DF=1时,每次操作后使SI和DI减小.DF=0时则增大.
		IF interrupt flag 中断标志 IF=1时,允许CPU响应可屏蔽中断,否则关闭中断.
		TF trap flag 陷阱标志 用于调试单步操作. 			
	*/

}
一、示例    
assume cs:cjcodesegment     
cjcodesegment segment   
mov ax,2    
add ax,ax   
add ax,ax   
mov ax,4c00H    
int 21H    
cjcodesegment ends      
end     
解析    
assume cs:cjcodesegment表示假设cs寄存器与cjcodesegment段有联系      
cjcodesegment segment表示cjcodesegment段开始   
mov ax,2    
add ax,ax   
add ax,ax   
cjcodesegment ends表示cjcodesegment段结束      
end表示 整个程序结束     
mov ax,4c00H    
int 21H     
这两条指令放在程序末尾让程序返回

二、mov与add
例一:
程序段中指令    指令执行后AX中数据  执令执行后BX中数据
mov ax,4E20H    4E20H               0000H
add ax,1406H    6226H               0000H
mov bx,2000H    6226H               2000H
add ax,bx       8226H               2000H
mov bx,ax       8226H               8226H
add ax,ax       044CH               8226H
注意:mov ax,[bx]表示ds:bx的内存值写入ax
例二:
已知(10000H)=23H,10001H=11H,10002H=22H,10003H=66H
mov ax 1000H    ax=1000H
mov ds,ax       ds=1000H
mov ax,[0]      ax=1121H
mov bx,[2]      bx=6622H
mov cx,[1]      cx=2211H
add bx,[1]      bx=8833H
add cx,[2]      cx=8833H
例三:
mov ax,123BH
mov ds,ax
mov ax,0
add ax,[0]
add ax,[2]
add ax,[4]
将数据段的前三个字加到ax

三、段地址
8086CPU可一次传16位即2个字节,win32反汇编时可以发现1次传4字节,注意物理地址=段地址*16+偏移地址,在十六进制表示时就是左移一位
mov bx,1000H//1000H就是16位,因为16进制下1个数字就是4位,两个数字就是一个字节,一次传1000H就是传两个字节
mov ds,bx
mov ax,[3]	//把(1000:3)10003H(低位)及10004H(高位)的数据读入ax
mov [3],cx	//把cx的数据读入(1000:3)10003H(低位)及10004H(高位)

四、栈地址
栈的地址是从1000FH到10000H,栈空时指向10010H,因为SP是16位,所以可以指向64K个字节范围,这个就是栈的量大范围
push ax
    sp=sp-2,即地址减小2字节(8086是16位)
    把ax写入ss:sp
pop ax
    把ss:sp写入ax
    sp=sp+2,即地址增加2字节(8086是16位)
例:
mov ax,1000H
mov ss,ax
mov sp,0010H
mov ax,001AH
mov bx,001BH
push ax
push bx
sub ax,ax   2B机器码,如果mov ax,0就是3个机器码
sub bx,bx   这里演示了AX与BX清0后用栈来恢复
pop bx      如果是先pop ax就是互换
pop ax

五、描述性符号
(x)就是取出x处的内容,例如:
(ax)=0010H          mov ax,0010H
(21000H)=0010H      mov [0],0010H(ds=2100H)
(ax)=((ds)*16+2)    mov ax,[2]
(ax)=(ax)+2         add ax,2
(ax)=(ax)+(bx)      add ax,bx
idata表示常量

六、loop
【先总结一下:转移指令:无条件jmp(改CS:IP),条件if,循环Loop,过程call/ret,中断】
(cx)=(cx)-1
判断cx非零就跳到标号,是0就往下执行
例:求2^12
assume cs:code
code segment
    mov ax,2
    mov cx,11
s:  add ax,ax
    loop s
    mov ax,4c00h
    int 21h
code ends
end

七、and
mov al,01100011B
and al,00111011B
此时al=00100011B

八、or
mov al,01100011B
and al,00111011B
此时al=01111011B

九、jmp
jmp short s表示s是一个8位的段内地址(直接操作数)
jmp near s表示s是一个16位的段内地址(直接操作数,可以理解为CS:IP计算出的具体值)
jmp far ptr s表示一个偏移位移即IP,是段间跳转(直接操作数,要预先赋好CS的值)
jmp word ptr s表示s明确给出CS:IP如ds:[0],或s是寄存器16位的值如[bx](内存或寄存器)
jmp dword ptr s表示s是ds:[0],从s处开始存两个字(4字节),后入栈的是目的段地址,先入栈的是目的偏移地址(内存或寄存器)
例一:
assume cs:codesg
codesg segment
    start:  mov ax,0
            jmp short s
            add ax,1    显然add这行代码没有被执行
    s:      inc ax
codesg ends
end start
注意:翻译成机器码时,上面的s会变成是相对于现在的地址而言偏移多少,所以机器中没有出现s
例二:
assume cs:codesg
codesg segment
start:  mov ax,0
        mov bx,0
        jmp far ptr s
        db 256 dup (0)
    s:  add ax,1
        inc ax
codesg ends
end start
注意:db 256 dup(0)表示填256个字节的0
例三:
mov ax,0123H
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds:[0]
执行后(CS)=0,(IP)=0123H,CS:IP指向0000:0123
例四:
mov ax,0123H
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr [bx]
执行后(CS)=0,(IP)=0123H,CS:IP指向0000:0123

十、jcxz
jcxz 标号
如果(cx)=0则转移到标号处执行,否则往下(这里与Loop相反,loop是非0时跳到标号,到0时往下)
例:实现在内存2000H段中查找第一个值为0的字节地址,并把偏移地址赋给dx
assume cs:code
code segment
start:  mov ax,2000H
        mov ds,ax
        mov bx,0
    s:  mov ch,0
        mov cl,[bx]
        jcxz ok
        int bx
        jmp short s
    ok: mov dx,bx
        mov ax,4c00h
        int 21h
code ends
end
变例:
assume cs:code
code segment
start:  mov ax,2000H
        mov ds,ax
        mov bx,0
    s:  mov ch,0
        mov cl,[bx]
        inc cx      因为loop s判断时会先让cx-1
        int bx
        loop s
    ok: mov dx,bx
        mov ax,4c00h
        int 21h
code ends
end

十一、ret
ret:用栈中数据修改IP,从而实现近转移,相当于pop IP
    (IP)=((SS)*16+(SP))
    (SP)=(SP)+2
retf:用栈中数据修改CS:iP,从而实现远转移,相当于pop IP,pop CS
    (IP)=((SS)*16+(SP))
    (SP)=(SP)+2
    (CS)=((SS)*16+(SP))
    (SP)=(SP)+2
例:让函数retf返回时回到1000:0000处执行
assume cs:code
stack segment
db 16 dup (0)
stack ends
code segment
start:  mov ax,stack
        mov ss,ax
        mov sp,16
        mov ax,1000H
        push ax
        mov ax,0000H
        push ax
        retf
code ends
end start

十二、call
一、call 标号
    (SP)=(SP)-2
    ((SS)*16+(SP))=(IP)
    (IP)=(IP)+16位位移
例:
内存地址    汇编指令
1000:0      mov ax,0
1000:3      call s
1000:6      inc ax
1000:7      s:pop ax
执行完(ax)=6,因为call时压入了IP=6
二、call far ptr 标号
    (SP)=(SP)-2
    ((SS)*16+(SP))=(CS)
    (SP)=(SP)-2
    ((SS)*16+(SP))=(IP)
    (CS)=标号所在段地址
    (IP)=标号所在偏移地址
简单来说就是     push CS
                push IP
                jmp far ptr 标号
例:
内存地址    汇编指令
1000:0      mov ax,0
1000:3      call far ptr s
1000:8      inc ax
1000:9      s:pop ax
            add ax,ax
            pop bx
            add ax,bx
执行完之后ax=1010H(8H+8H+1000H)
三、call 16位寄存器
    (SP)=(SP)-2
    ((SS)*16+(SP))=(IP)
    (IP)=(16位寄存器)
简单来说就是push IP,jmp 16位寄存器
例:
内存地址    汇编指令
1000:0      mov ax,6
1000:3      call ax
1000:5      inc ax
1000:6      mov bp,sp
            add ax,[bp]
执行完之后AX+6+5=0BH
四、call word ptr 内存单元地址
mov sp,10h
mov ax,0123h
mov ds:[0],ax
call word ptr ds:[0]
执行后,(IP)=0123H,(SP)=0EH(由10h-2可得)
简单来说就是push IP,jmp word ptr 内存单元地址
五、call dword ptr 内存单元地址
mov sp,10h
mov ax,0123h
mov ds:[0],ax           在ds:[0]与ds:[1]存的就是call行要压入IP的0123H
mov word ptr ds:[2],0   在ds:[2]与ds:[3]存的就是call行要压入CS的0
call dword ptr ds:[0]
执行后,(CS)=0,(IP)=0123H,(SP)=0CH(由10h-2-2可得)
简单来说就是push IP,push CS,jmp dword ptr 内存单元地址

总结区分好:
一二的标号是直接操作数(二的标号是IP,CS与预先存),三是用寄存器,四五都是内存地址
其中四是用ds:[0]与ds:[1]两个字节组成IP,而五是用ds:[0]与ds:[1]两个字节组成IP基础上用用ds:[2]与ds:[3]两个字节组成CS
当然,ds:[0]与ds:[1]是高字节还是低字节在前面那就是大小端模式考的内容了
记住:ds是01存IP,23存CS,栈中是栈底即高地址存CS,栈顶即低地址存IP

十三、call与ret
assume cs:code
code segment
start:  mov ax,1
        mov cx,3
        call s
        mov bx,ax
        mov ax,4c00h
        int 21h
    s:  add ax,ax
        loop s
        ret
code ends
end start
执行完后(bx)=8

十四、mul
mul 8位reg
mul byte ptr ds:[0]
8位相乘:AL与8位寄存器或内存字节单元相乘,结果放在AX中
mul 16位reg
mul word ptr [bx+si+8]
16位相乘:AX与16位寄存器或内字字单元相乘,结果放在DX高位与AX低位中
例:
mov al,100
mov bl,10
mul bl
执行完(ax)=1000(03E8H)
例:
mov ax,100
mov bx,10000
mul bx
执行完(ax)=4240H,(dx)=000FH,因为F4240H=1000000
例:
mov ax,bx
mul bx
mul bx
ret
这时AX就是BX的3次方

十五、传参
dw表示data word
dd表示data dword
例:实现对数组的每个元素都乘三次方,注意cube函数中是(dx,ax)=ax*bx
assume cs:code
data segment
dw 1,2,3,4,5,6,7,8
dd 0,0,0,0,0,0,0,0
data ends
code segment
start:  mov ax,data
        mov ds,ax
        mov si,0
        mov di,16
        mov cx,8
    s:  mov bx,[si]
        call cube
        mov [di],ax
        mov [di+2],dx
        add si,2
        add di,4
        loop s
        mov ax,4c00h
        int 21h
    cube:   mov ax,bx
            mul bx
            mul bx
            ret
code ends
end start
例:实现对字符串变成大写,就是把一个位清0就是变大写,97a变65A
assume cs:code
data segment
db 'conversation'
data ends
code segment
start:  mov ax,data
        mov ds,ax
        mov si,0
        mov cx,12
        call captital
        mov ax,4c00h
        int 21h
captital:   and byte ptr [si],11011111b
            inc si
            loop captital
            ret
code ends
end start
例:不知字符串长度但知道最后一个字符的下一位是0
capital:    mov cl,[si]
            mov ch,0
            jcxz ok
            and byte ptr [si],11011111b
            inc,si
            jmp short capital
    ok:     ret

十六、标志寄存器
ZF:计算结果为0置1,否则清0,是Flag第六位
例: mov ax,1   
    sbu ax,1
    则ZF=1
PF: 奇偶校验位,偶数个1是为1,奇数个1时为0,是Flag第二位
SF:符号位,负数是1,正数是0,是Flag第七位,只对有符号数运算有意义
CF:进位标志,是flag的第零位,记录运算结果的最高有效位的进位情况,有进位是1,无进位是0,只对无符号数运算有意义
OF:溢出位,进行符号运算时结果超过机器所能表示的范围为溢出,只对有符号数运算有意义
例: mov al,98H
    all al,99H
注意只受运算指令如add/sub/mul/div/inc/or/and影响,不受传送指令影响如mov/push/pop
汇编指令     al  ZF  PF  SF
sub al,al   0h  1   1   0
mov al,1    1h  1   1   0   不受影响
push ax     1H  1   1   0   不受影响
pop bx      1H  1   1   0   不受影响
add al,bl   2H  0   0   0
add al,10H  12H 0   1   0
mul al      144H 0  1   0   144H=10010000B是偶数个1

十七、CMP与jump
cmp ax,ax即(ax)-(ax),则zf=1,pf=1,sf=0,cf=0,of=0,但ax没有变化
jz表示ZF标志位为1时跳,je等于时跳,jne不等于时跳,jb小于时跳,jnb不小于时跳,ja大于时跳,jna不大于时跳,jnge不大于或等于(就是小于)
ja与jg的区别是ja无符号比较(above),jg带符号比较,jb与jl的区别是jb是无符号比较(below),jl是有符号比较

十八、字符串压栈
push offset 字符串长

十九、调用约定
cdecl是默认约定,针对用户自己写的函数,在调用函数返回后手动退栈	 				
stdcall是API约定,针对windows官方函数,在调用函数返回时自动退栈
fastcall是快速约定,传参时优先使用寄存器

二十、st0到st7
八个80位的两用寄存套,MMX或FPU
指令使用:

#include <Windows.h>
int add(int a, int b) {
	return a + b;
}
int aaa = 1;
int bbb = 1;
int main(){
	MessageBox(0, NULL, NULL, MB_OK);
	aaa = add(0x11, 0x22);  
	__asm mov bbb,0x778899 //这就是在C++中引用ASM代码!
	return 0;
	/*
	F2断点
	F4运行到选定位置
	F7步入,单步执行入函数
	F8步过,单步执行不入函数
	F9运行到下一断点
	ALT+F9:执行到用户代码
	CTRL+F9:执行到返回

	有时无法选中代码:可以右键-分析-分析代码,然后右键,分析-删除模块分析,即可选中
	*/
	
}

汇编学习笔记

汇编学习笔记

#include<windows.h>
#include<cstdio>
int main() {				//AX是EAX的低16位
	char c = -0x33;			//0xCD
	int i = 0x87654321;		//下面两行转成汇编就是movsx(扩展位与原最高位相同)与movzx(扩展位是0)
	i = c;					//24个1 11001101,MOVSX i,c
	i = (unsigned char)c;	//24个0 11001101,MOVZX i,c
	int* p = &i;			//LEA p,i	

	int x = 3, y = 4;
	if (x < 2) {
		printf("<<<");
	}
	else if (x > 4) {
		printf(">>>");
	}
	else {
		printf("===");
	}

	switch (x + y) {
	case 3 :
		printf("333\n");
		break;
	case 5 :
		printf("555\n");
		break;
	case 7 :
		printf("777\n");
		break;
	default:
		printf("default");
		break;
	}

	for (int i = 1; i <= x; i++) {
		printf("%d\n",i);
	}


	system("pause");
	return 0;
}

/*
01021080 >/$  55            push ebp
01021081  |.  8BEC          mov ebp,esp
01021083  |.  83EC 20       sub esp,0x20
01021086  |.  A1 04300201   mov eax,dword ptr ds:[__security_cookie_>
0102108B  |.  33C5          xor eax,ebp
0102108D  |.  8945 FC       mov [local.1],eax
01021090  |.  C645 F7 CD    mov byte ptr ss:[ebp-0x9],0xCD
01021094  |.  C745 F8 21436>mov [local.2],0x87654321
0102109B  |.  0FBE45 F7     movsx eax,byte ptr ss:[ebp-0x9]
0102109F  |.  8945 F8       mov [local.2],eax
010210A2  |.  0FB64D F7     movzx ecx,byte ptr ss:[ebp-0x9]
010210A6  |.  894D F8       mov [local.2],ecx                        ;  test05.<ModuleEntryPoint>
010210A9  |.  8D55 F8       lea edx,[local.2]
010210AC  |.  8955 E0       mov [local.8],edx                        ;  test05.<ModuleEntryPoint>
010210AF  |.  C745 F0 03000>mov [local.4],0x3
010210B6  |.  C745 E4 04000>mov [local.7],0x4
010210BD  |.  837D F0 02    cmp [local.4],0x2
010210C1  |.  7D 0F         jge short test05.010210D2
010210C3  |.  68 00210201   push test05.01022100
010210C8  |.  E8 73FFFFFF   call test05.printfTStartupr_initialize_m>
010210CD  |.  83C4 04       add esp,0x4
010210D0  |.  EB 22         jmp short test05.010210F4
010210D2  |>  837D F0 04    cmp [local.4],0x4
010210D6  |.  7E 0F         jle short test05.010210E7
010210D8  |.  68 04210201   push test05.01022104
010210DD  |.  E8 5EFFFFFF   call test05.printfTStartupr_initialize_m>
010210E2  |.  83C4 04       add esp,0x4
010210E5  |.  EB 0D         jmp short test05.010210F4
010210E7  |>  68 08210201   push test05.01022108
010210EC  |.  E8 4FFFFFFF   call test05.printfTStartupr_initialize_m>
010210F1  |.  83C4 04       add esp,0x4
010210F4  |>  8B45 F0       mov eax,[local.4]                        ;  kernel32.746A8654
010210F7  |.  0345 E4       add eax,[local.7]
010210FA  |.  8945 E8       mov [local.6],eax
010210FD  |.  837D E8 03    cmp [local.6],0x3
01021101  |.  74 0E         je short test05.01021111
01021103  |.  837D E8 05    cmp [local.6],0x5
01021107  |.  74 17         je short test05.01021120
01021109  |.  837D E8 07    cmp [local.6],0x7
0102110D  |.  74 20         je short test05.0102112F
0102110F  |.  EB 2D         jmp short test05.0102113E
01021111  |>  68 0C210201   push test05.0102210C                     ;  ASCII 33,"33\n"
01021116  |.  E8 25FFFFFF   call test05.printfTStartupr_initialize_m>
0102111B  |.  83C4 04       add esp,0x4
0102111E  |.  EB 2B         jmp short test05.0102114B
01021120  |>  68 14210201   push test05.01022114                     ;  ASCII 35,"55\n"
01021125  |.  E8 16FFFFFF   call test05.printfTStartupr_initialize_m>
0102112A  |.  83C4 04       add esp,0x4
0102112D  |.  EB 1C         jmp short test05.0102114B
0102112F  |>  68 1C210201   push test05.0102211C                     ;  ASCII 37,"77\n"
01021134  |.  E8 07FFFFFF   call test05.printfTStartupr_initialize_m>
01021139  |.  83C4 04       add esp,0x4
0102113C  |.  EB 0D         jmp short test05.0102114B
0102113E  |>  68 24210201   push test05.01022124                     ;  ASCII 64,"efault"
01021143  |.  E8 F8FEFFFF   call test05.printfTStartupr_initialize_m>
01021148  |.  83C4 04       add esp,0x4
0102114B  |>  C745 EC 01000>mov [local.5],0x1
01021152  |.  EB 09         jmp short test05.0102115D
01021154  |>  8B4D EC       /mov ecx,[local.5]
01021157  |.  83C1 01       |add ecx,0x1
0102115A  |.  894D EC       |mov [local.5],ecx                       ;  test05.<ModuleEntryPoint>
0102115D  |>  8B55 EC        mov edx,[local.5]
01021160  |.  3B55 F0       |cmp edx,[local.4]                       ;  kernel32.746A8654
01021163  |.  7F 13         |jg short test05.01021178
01021165  |.  8B45 EC       |mov eax,[local.5]
01021168  |.  50            |push eax
01021169  |.  68 2C210201   |push test05.0102212C                    ;  ASCII 25,"d\n"
0102116E  |.  E8 CDFEFFFF   |call test05.printfTStartupr_initialize_>
01021173  |.  83C4 08       |add esp,0x8
01021176  |.^ EB DC         \jmp short test05.01021154
01021178  |>  68 30210201   push test05.01022130                     ; /command = "pause"
0102117D  |.  FF15 78200201 call dword ptr ds:[<&api-ms-win-crt-runt>; \system
01021183  |.  83C4 04       add esp,0x4
01021186  |.  33C0          xor eax,eax
01021188  |.  8B4D FC       mov ecx,[local.1]
0102118B  |.  33CD          xor ecx,ebp
0102118D  |.  E8 04000000   call test05.__security_check_cookieprese>
01021192  |.  8BE5          mov esp,ebp
01021194  |.  5D            pop ebp                                  ;  kernel32.746A8654
01021195  \.  C3            retn

*/

 

上一篇:汇编实验九(王爽)


下一篇:汇编语言(王爽)第八章