0.asm-8086汇编

1.汇编语言发展至今,由以下3类指令组成

汇编指令:有对应的机器码

伪指令:没有机器码,由编译器执行

其他符号:没有机器码,由编译器识别


2.在内存或磁盘中,指令和数据没有任何区别,都是二进制信息


3.CPU是可以执行机器指令的微处理器,要想让它工作,就必须向它提供指令和数据,即存储器(内外存)

它们要交互:

1)存储单元的地址(地址、从哪起始)

2)读或写命令(控制信息)

3)读或写的数据(数据)

这三者当然是通过电信号传递,也即导线,连接CPU和其他芯片的导线,通常称为总线:即以上三类(地址、控制、数据)总线(外部总线


4.存储器的容量是以字节为最小单位计算的,所有的物理存储器都被看作一个由若干存储单元组成的逻辑存储器,此大小受地址总线限制,8086为2~20次方即1M

80386为2~32次方,即4G


5.CPU由运算器、控制器、寄存器等器件构成(说明下,存储器和寄存器名字相似,这两者可是相差千万),内部总线连接它们,进行数据传送

ax,bx,cx,dx为通用寄存器,为了向上兼容,又可以分为h+l两类8字节的,如ax可以分为ah+al

以下为基础赋值

mov ax,18
mov ah,78
add ax,8
mov ax,bx
add ax,bx

6.如

mov ah,0
mov al,c5H
add al,93H
ax的值是0058H,此时al做为独立的8位寄存器使用,和ah没有关系,CPU在执行时会认为ah和al是两不相关的寄存器

7.所有内存单元构成的存储空间,每个内存单元在这空间中都有唯一的地址(物理地址),CPU通过地址总线送入存储器,必须是一个物理地址,所以在它发出这个地址之前,它要先在内部形成这个物理地址,不同的CPU有不同的形成方式

8086有20位地址总线,也就是存储空间可以是2~20次方,而它的寄存器只有16位,所以必须2个一起组合(段地址+偏移地址)

地址加法器会把它们转换成20位物理地址,物理地址=段地址*16+偏移地址


8.段地址可以在编程中视为起始地址,因为段地址*16必然是16的部数,所以段超始地址也一定是16的倍数,偏移地址为16位,所以最大长度为64K

CPU可以通过不同的段地下+偏移地址形成同一个物理地址

CS、DS、SS、ES为段寄存器


9.CS:IP执行指令的过程是:

1)地址加法器转换CS*16+IP为物理地址,通过总线,找到外部的这个物理地址,读取指令进入指令缓冲区

2)IP=IP+所读取指令的长度,从而指向下一条指令

3)执行指令,转到步骤1)

所以CPU就是通过CS:IP来把内存单元的内容看成指令的,不然指令和数据没有任何区别


10.mov是不能改变CS、IP的值,能够改变它们的指令统称为转移指令,如jmp

jmp 2AE3:3执行后,CS=2AE3,IP=003
jmp ax执行后,CS不变,IP=ax
  

11.win7-64模拟debug:下载地址

1.安装dosbox,运行,debug.exe放在d盘
2.输入命令mount c d:\
当出现Drive C is mounted as local directory d:\的时候,成功
"c"是作为虚拟c盘的意思,"d:\"是虚拟文件夹的位置(debug.exe)
3.输入c:
4.输入debug
u查看汇编,a编缉汇编 ,windbg估计就是抄它的吧

先q:退出,再cls清屏


12.8086不支持把数据直接送到段寄存器中,即不能mov ds, 1000h

所以这样写:

mov bx,1000h
mov ds,bx
[addr]意为取addr地址的内容, 注意在x86下,只有mov eax,[ebx]这样才是取内容,其他的如mov eax,1或mov eax,[1]或mov eax,g_var或mov eax,[g_var]都是赋值

这其实也是debug和masm对指令的不同处理,目前的解决方式就是都是先赋到寄存器中,再mov eax,[ebx]这样(112page)

mov 寄存器,数据mov ax,8
mov 寄存器,寄存器mov ax, bx
mov 寄存器,内存单元mov ax,[0]
mov 内存单元,寄存器mov [0],ax
mov 段寄存器,寄存器mov ds,ax


13.栈
栈增加是从地址高到地址低增长的,任意时刻,SS:SP都指向栈顶元素,当栈空时,即不存在栈顶元素,所以SS:SP只能指向栈最底部单元下面的单元


push ax:

1).SP=SP-2

2).ax送入SP所在位置


pop ax

1)将SP所在位置的值送入ax中(注意栈是从高向低的)

2)SP=SP+2


14.栈溢出

栈满再执行push,就会覆盖到栈顶以上的数据(即比栈顶还小的地址被覆盖)

栈空再执行pop,会pop栈底以下的数据

由于SP是16位的,所以如果栈底是0XFFFE时,再POP就变成0了,再POP就变成2了



15.loop指令

1).cx = cx-1

2).判断cx中的值,不为0,则转到标号执行


16.伪指令assume cs:code,ds:data,ss:stack,这样做后,CPU是不会把csr指向code,ds指向data的,这就是一个标识,仅此而已

所以还是要自己在代码中传递


17.可以用' '单引号把字符串转换成对应的ASII码,一个字符对应一个字节转换,所以

	__asm
	{
		push eax
		mov eax, 'cdef'
		pop eax
	}
这样是正确的,eax支持四个字节,所以1到4个字节都是OK的,多了就会报错

18.[bx+idata]表示内存单元

char *g_char = "123456";
int main()
{
	__asm
	{
		push eax
		mov ebx, g_char
		mov eax, [ebx+1]
		pop eax
	}
像mov eax, [ebx+ecx+1]也是OK的

19.在没有寄存器名存在的情况下,用操作符X PTR指明内存单元的长度,X可以为DWORD,WORD BYTE等


20.可以修改CS:IP的相关指令统称为转移指令

1>.无条件转移指令(jmp)

2>条件转移指令

3>循环指令(loop)

4>过程

5>中断

offset用于取得标号的偏移地址:在386中取得标号在程序中的地址

如:

char *g_char = "123456";
int main()
{
	__asm
	{
		push eax
s:
		mov eax, offset s
s1:      
		mov eax, offset s1
		pop eax
	}
编译后反汇编是如下的:



20.jcxz s如果cx=0,则转到s,否则无视它


21.call 对当前下一条指令的IP压栈,再跳转 ret对IP出栈


22.标志寄存器(一般运算指令会影响,如add、sub、mul、div、inc、or、and,而传送执行是没有影响的,如mov、push、pop)

ZF:结果为0,zf=1

        PF:1的个数为偶数,pf=1

SF:负数时sf=1

DF:为0,循环操作时,si、di递增,否则递减

溢出标志OF(Over flow flag) OV(1) NV(0)

方向标志DF(Direction flag) DN(1) UP(0)

中断标志IF(Interrupt flag) EI(1) DI(0)

符号标志SF(Sign flag) NG(1) PL(0)

零标志ZF(Zero flag) ZR(1) NZ(0)

辅助标志AF(Auxiliary carry flag) AC(1) NA(0)

奇偶标志PF(Parity flag) PE(1) PO(0)

进位标志CF(Carry flag) CY(1) NC(0)

CF: 无符号数运算时记录进位值或借位值,有则为1

mov al,98h
add al,al //al=30h,cf=1,进位

mov al,97h
sub al,98h//al=ffh,cf=1,借位了

OF:有符号数溢出则为1

如前面add al,al,就会有溢出of=1

adc ax,bx 等于 ax = ax+bx + cf(0或1)

所以

add ax,bx
=
add al,bl
adc ah,bh
sbb相反


23.cmp指令相当于减法指令,只是不保存结果,但影响标志寄存器

cmp ax, bx的逻辑含义:

zf=1 说明 ax = bx
zf=0 说明 ax !=bx
cf=1 说明 ax < bx
cf=0 说明 ax >= bx
cf=0&&zf=0说明ax>bx
cf=1或zf=1,说明ax<=bx

24.条件转移指令

1>无符号比较:

je    等于则转移         zf =1
jne  不等于则转移      zf = 0
jb    低于则转移         cf = 1
jnb   不低于则转移     cf = 0
ja    高于则转移         cf = 0&&zf=0
jna   不高于则转移     cf = 1或zf = 1

25.串传送

movsb将ds:si指向的内存字节送入es:di中,然后根据df位,将si和di递增或递减1

movsw将ds:si指向的内存字送入es:di中,然后根据df位,将si和di递增或递减2

rep movsb
= 
s: movsb
    loop s
所以rep也是根据CX的值来重复的

assume cs:code, ds:data
	data segment
		db 'Welcome to masm'
		db 16 dup(0)
	data ends
	code segment 
start:
	mov ax, data
	mov ds, ax
	mov si, 0
	mov es, ax
	mov di, 16
	mov cx, 16
	cld
	rep movsb
	
	mov ax, 4c00h
	int 21h
	code ends 
	
end start
char *g_char = "123456";
int main()
{
	char* pCopy = new char[10];
	memset(pCopy,0,10);
	__asm
	{
		pushad
		pushfd
	
		mov esi,g_char
		mov edi,pCopy
		cld
		mov cx, 6
		rep movsb

		popfd
		popad
	}
	getchar();
std对应df=1


26.pushf 、popf将标志寄存器压栈、出栈,i386下是pushfd、popfd


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值