编写汇编
定义一个段
- segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指令。
- segment和ends的功能是定义一个段,segment说明一个段的开始,ends说明一个段的结束。
- 一个段必须有一个名称来表示,使用格式为:
- 段名 segment
- 段名 ends
- 一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当做栈空间来使用。
-
end
end是汇编程序的结束标记,如果碰到伪指令end,就结束对源程序的编译。
程序写完了,在结尾加上伪指令end,不然无法知道程序何时结束。
assume
他假设某一段寄存器和程序中的某一个用segment···ends定义的段相关联。
- 通过assume说明这种关联,在需要的情况下,编译程序可以将段寄存器和某一个具体的段相联系。
汇编源程序
伪指令(编译器处理)
汇编指令(编译为机器码)
程序:源程序中最终由计算机执行、处理的指令或数据。源程序
任务:编写运算2^3。 ``` assume cs:abc
abc segment mov ax,2 mov bx,2 mul ax mul bx
mov ax,4c00H int 21H abc ends
end abc ends
end
<a name="d2WDm"></a>#### 程序返回应该在程序的末尾添加返回的程序段。<br />mov ax,4c00H<br />int 21H<br />这两台指令所实现的功能就是程序返回。<a name="jzfRO"></a>## 多个段的程序- 对于使用多个段的问题:编程计算以下4个数据的和,结果存放在ax寄存器中。0123H,0456,0123H,0123H- 在一个段中存放数据、代码、栈
assume cs:codesg
codesg segment
tong:
dw 0123H,0123H,0123H,0123H,0123H,0123H,0123H,0123H,0123H
xor bx,bx
xor ax,ax
mov cx,9h
s: add ax,cs:[bx]
add bx,2
loop s
mov ax,4c00Hint 21H
codesg ends end tong
dw:定义字型数据。define word 16b。<br />在程序的第一条指令的前面加上了一个标号start,而这个标号在伪指令end的后面出现。<br />end出了通知编辑器程序结束之外,还可以通知编译器程序的入口在什么地方。- 将一段数据放入栈中,实现逆序存放
assume cs:codesg
codesg segment
start:
dw 0ffffH,0123H,0123H,0123H,0123H,0123H,0123H,0123H
dw 0,0,0,0,0,0,0,0
mov bx,0mov cx,8s: push cs:[bx]add bx,2loop smov cx,8mov bx,0s0: pop cs:[bx]add bx,2loop s0mov ax,4c00Hint 21H
codesg ends end start
- 将数据、代码、栈放入不同的段- 如果数据、栈和代码需要的空间超过64KB,就不能放在一个断中。8086模式的限制,不是每个处理器都是这样。
assume cs:code,ds:data,ss:stack
data segment
dw 0ffffH,0123H,0123H,0123H,0123H,0123H,0123H,0123H
data ends
stack segment dw 0,0,0,0,0,0,0,0 stack ends
code segment
start:
mov ax,stack 分配栈空间
mov ss,ax
mov sp,16 设置栈顶ss:sp stack:16
mov ax,data 分配data空间
mov ds,ax ds指向data段
mov bx,0
mov cx,8
s: push [bx]
add bx,2
loop s
mov cx,8mov bx,0s0: pop [bx]add bx,2loop s0mov ax,4c00Hint 21H
code ends end start
就是秀~~~我也太强了。- 代码段、数据段、栈段完全是我们自己定义的。- 用来存放数据段的:data- 用来存放代码段的:code- 用来存放栈空间的:stack<a name="Hv3vK"></a>## and&or这个太简单了,没啥好写的。<a name="opaaf"></a>## ASCII码- 世界上很多编码方案,ASCII是计算机通常被采用的- 编码就是一套规则,用干什么样的信息来表示现实对象- 比如61H表示'a'- mov al,'a'相当于mov al,61H- 大小写转换
code segment
start:
mov al,’A’
or al,20h
and al,0dfh
mov ax,4c00Hint 21H
code ends end start
<a name="Sp0Av"></a>## [bx+idata]- mov ax,[bx+200]的含义- 将一个内存单元的内容送入ax,这个内存单元的长度为2字节,存放一个字,偏移地址为bx中的数据加上200,段地址在ds中。- 数学化描述:mov ax,[bx+200]=((ds)*16+(bx)+200)- 数组的处理
datasg segment db ‘abcdefghijklm’ db ‘nopqrstuvwxyz’ datasg ends
code segment
start:
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,13
s: mov al,[bx]
and al,11011111b
mov [bx],al
mov al,[bx+13] —[bx+13]可以表示为13[bx],是不是特别像数组
and al,11011111b
mov [bx+13],al
inc bx
loop s
mov ax,4c00Hint 21H
code ends end start
<a name="DWnuy"></a>## SI&DI- SI和DI是8086CPU中与BX功能相近的寄存器,但是SI和DI不能够分成两个8位寄存器来使用。- 将“tong ge shuai bi”用si,di复制到“................”中
datasg segment db ‘tong ge shuai bi’ db ‘…………….’ datasg ends
code segment
start:
mov ax,datasg
mov ds,ax
mov si,0
mov di,13
mov cx,13
s: mov al,[si]
mov [di],al
inc di
inc si
loop s
mov ax,4c00Hint 21H
code ends end start
<a name="XghvJ"></a>## 不同的寻址方式和灵活应用- 几种定位内存地址的方法- [iata]用一个常量来表示地址,可用于直接定位一个内存单元- [bx]用一个变量来表示内存地址,可用于间接定位一个内存单元- [bx+idata]用一个变量和常量表示地址,可在一个起止的基础上用变量间接定位一个内存单元- [bx+si]用两个变量表示地址- [bx+si+idata]用两个变量和一个常量表示地址- 讲前四个字母换成大写字母
stack segment dw 0,0,0,0,0,0,0,0 stack ends
datasg segment db ‘tonggeshuai…..’ db ‘deyipi……….’ datasg ends
code segment
start:
mov ax,datasg
mov ds,ax
mov ax,stack
mov ss,ax
xor bx,bx
mov cx,2
s0:push cx
mov cx,4
xor si,si
s1:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s1
pop cx
add bx,10h
loop s0
mov ax,4c00Hint 21H
code ends end start
实现了双重循环。吊的一批~~~~<a name="yOjOK"></a>## 寄存器集合- reg:ax、bx、cx、dx、ah、al、bh、bl、ch、cl、dh、dl、sp、bp、si、di- sreg:ds、ss、cs、es- 在8086寄存器中,只有bx、bp、si、di可以用在[...]中进行内存寻址- 在[...]中只能以四个组合出现- bx&si、bx&di、bp&si、bp&di- 指令中没有设置段地址(ds没给值),[bp]的段地址默认给ss的段- mov ax,[bp]=((ss)*16+bp)<a name="fCrw6"></a>## 寻址方式关于DEC公司的一条记录:<br />公司名称:DEC 在内存中如下存放<br />总裁姓名:Ken Olsen seg:60+00<br />排 名:137 'DEC'<br />收 入:40 +03 <br />著名产品:PDP 'ken slsen'<br />2021年同哥的加入公司有了新变化: +0C1. Ken Olsen在富翁榜上的排名已升至38位; 1371. DEC的收入增加了70亿美元; +0E1. 该公司的著名产品已变为VAX系列计算机。 40任务:编程修改内存中的过时数据。 +10 <br /> 'PDP'
code segment
start:
mov bx,60h
mov si,0
mov word ptr [bx+0Ch],137d
mov word ptr [bx+0Eh],40d
mov byte ptr [bx+10h+si],’P’
inc si
mov byte ptr [bx+10h+si],’D’
inc si
mov byte ptr [bx+10h+si],’P’
inc si
xor si,simov word ptr [bx+0ch],38dmov ax,[bx+0eh]add ax,70dmov word ptr [bx+0eh],axmov byte ptr [bx+10h+si],'V'inc simov byte ptr [bx+10h+si],'A'inc simov byte ptr [bx+10h+si],'X'inc simov ax,4c00Hint 21H
code ends end start
<a name="reOHz"></a>## div指令- div是触发指令,使用div作触发的时候:- 除数:8位或16位,在寄存器或内存单元中- 被除数:(默认)放在ax或dx和ax中- 除数 被除数- 8位 16位(ax)- 16位 32位(dx+ax)- 结果:运算 8位 16位商 AL AX<br /> 余数 AH DX- div byte ptr ds:[0]- (al)=(ax)/((ds)*16+0)的商- (ah)=(ax)/((ds)*16+0)的余数- div word ptr es:[0]- (ax)=[(dx)*10000H+(ax)]/((ds)*16+0)的商- (dx)=[(dx)*10000H+(ax)]/((ds)*16+0)的余数- 利用除法指令计算100001/100
code segment
start:
mov dx,1h
mov ax,86a1h
mov bx,100h
div bx
mov ax,4c00Hint 21H
code ends end start
伪指令dd- db和dw定义字节型数据和字型数据。- dd是用来定义dword(double word双字)型数据的。- db 1:01H- dw 1:00 01H- dd 1:00 00 00 01H
code segment
start:
mov bx,0h
mov si,0h
mov [bx+si],word ptr 86a1h
add si,2h
mov [bx+si],word ptr 1h
add si,2h
mov [bx+si],word ptr 100d
add si,2h
mov [bx+si],word ptr 0d
mov ax,[0]mov dx,[2]div word ptr [4]mov [6],axmov ax,4c00Hint 21H
dup
- db 3 dup(0)
- 定义了3个字节,都为0
- 0,0,0
- db 3 dup(0,1,2)
- 定义了9个字节
- 0,1,2,0,1,2,0,1,2
- db 3 dup(‘abc’,’ABC’)
- 定义了18个字节
- abcABCabcABCabcABC
