处理字符问题
汇编程序中,用单引号('')的方式指明数据是以字符的形式给出,编译器将把字符转换为相对应的ASCLL码。
大写字母ASCLL值 + 20H 转换为小写字母 (或运算or) 0010 0000
小写字母ASCLL值 - 20H 转换为大写字母 (与运算and) 1101 1111
示例:
大小写转换
assembly
assume cs:codesg, ds:datasg
datasg segment
db 'BaSiC'
db 'iNfOrMaTiOn'
dataseg ends
codesg segment
start:
mov ax, datasg
mov ds,ax
mov bx,0
mov cx,5
s:mov al,[bx]
and al,11011111b
mov [bx],al
inc bx
loop s
mov bx,5
mov cx,11
s0:mov al,[bx]
or al,00100000b
mov [bx],al
inc bx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
; debug查看原始数据
; d 数据段地址:0
; g
; d 数据段地址:0
[bx+idata]的含义
[bx+idata]表示一个内存单元,偏移地址为(bx)+idata(bx中的数值加上idata)。
mov ax,[bx+200]的含义
- 将一个内存单元的内容送入ax
- 该内存单元的长度为2字节(字单元)
- 内存单元的段地址在ds中,偏移地址为200加上bx中的数值
- 数学化的描述为:(ax) = ((ds) *16 + 200 + (bx))
其它写法如下:
assembly
mov ax,[200 + bx]
mov ax,200[bx]
mov ax,[bx].200
SI和DI寄存器
- 通用寄存器: AX,BX,BX,DX
- 变址寄存器: SI,DI
- 指针寄存器: SP,BP
- 指令指针寄存器: IP
- 段寄存器: CS,SS,DS,ES
- 标志寄存器: PAW
其中SI和DI执行与地址有关的操作。
SI: source index,源变址寄存器
DI: destination index,目标变址寄存器
示例如下:
assembly
mov bx,0
mov ax,[bx] ; 方式一
mov si,0
mov ax,[si] ; 方式二
mov di,0
mov ax,[di] ; 方式三
assembly
mov bx,0
mov ax,[bx+123] ; 方式一
mov si,0
mov ax,[si+123] ; 方式二
mov di,0
mov ax,[di+123] ; 方式三
应用SI,DI寄存器
采用寄存器SI和DI实现将字符串'welcome to masm!' 复制到之后的内存区中。源数据起始地址:datasg:0,目标数据起始地址:datasg:16
- 用ds:si指向需要复制的原始字符串
- 用ds:di指向目的空间
assembly
assume cs:codesg, ds:datasg
datasg segment
db 'welcome to masm!'
db '.................'
datasg ends
codesg segment
start: mov ax,datasg
mov ds,ax
mov si,0
mov di,16
mov cx,8
s:mov ax,[si]
mov [di],ax
add si,2
add di,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
二维数组循环的处理,将每个单词改为大写字母。
assembly
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
codesg segment
start:
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0:mov dx,cx ; 将外层循环的cx值保存在dx
mov si,0
mov cx,3 ; cx设置为内存循环的次数
s: mov al,[bx+si]
and al,11011111b
mov [bx+si], al
inc si
loop s
add bx,16
mov cx,dx ; 用dx存放的外层循环计数值恢复cx
loop s0 ; (cx) = (cx) - 1针对外层循环
codesg ends
end start
内存寻址方式
形式 | 名称 | 特点 | 意义 | 示例 |
---|---|---|---|---|
[idata] | 直接寻址 | 用一个常量/立即数表示地址 | 用于直接定位一个内存单元 | mov ax,[200] |
[bx] | 寄存器间接寻址 | 用变量表示内存地址, | 用于间接定位一个内存单元 | mov bx,0 mov ax,[bx] |
[bx + data] | 寄存器相对寻址 | 用变量和常量表示地址,可用于结构体,数组,二维数组 | 在一个起始地址的基础上用变量间接定位一个内存单元 | mov bx,4 mov ax,[bx+200] |
[bx + si] | 基地址变址寻址 | 用两个变量表示地址,可用于二维数组 | mov ax,[bx+si] | |
[bx+si+idata] | 相对基址变址寻址 | 用两个变量和一个常量表示地址,可用于二维数组 | mov ax,[bx+si+200] |
声明数据大小
在没有寄存器参与的内存单元访问指令中,用word ptr(2字节)或byte ptr(1字节)显示地指明所要访问的内存单元长度,否则,cpu无法得知所要访问的单元是字单元,还是字节单元。
assembly
mov word ptr ds:[0],1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx],2
mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2
div指令
除法指令。
- 被除数: 默认放在ax或dx和ax中
- 除数: 8位或16位,在寄存器或内存单元中
被除数 | AX | DX和AX |
---|---|---|
除数 | 8位内存或寄存器 | 16位内存或寄存器 |
商 | AL | AX |
余数 | AH | DX |
示例如下:
div bl | ax | bl | al | ah |
---|---|---|---|---|
div bx | (dx)*10000H+(ax) | bx | ax | dx |
在默认的寄存器中设置好被除数,且默认寄存器不做其它用处。
dup指令的功能和用法
dup和db,dw,dd等数据定义伪指令配合使用,用来进行数据的重复。
指令 | 功能 | 结果 |
---|---|---|
db 3 dup(0) | 定义三个字节,值都是0 | db 0,0,0 |
db 3 dup(0,1,2) | 定义了九个字节,由1,2,3重复三次组成 | db 0,1,2,0,1,2,0,1,2 |
db 3 dup('abc','ABC') | 定义了18个字节,构成了abcABCabcABCabcABC | db 'abcABCabcABCabcABC' |
使用格式为:
assembly
; db 重复的次数 dup (重复的字节型数据)
; dw 重复的次数 dup (重复的字节型数据)
; dd 重复的次数 dup (重复的字节型数据)