and指令,逻辑运算 &按位与运算 都真为真
mov al, 0110 0011B
and al, 0011 1011B
执行后al=0010 0011B
通过该指令可以将操作对象的相对位设置为0
mov al, 1111 1111B
and al, 1011 1111B
执行后al=1011 1111B
将操作对象的第6位设置为0
or指令,逻辑运算 | 按位或运算 都假为假
mov al, 0110 0011B
or al, 0011 1011B
执行后al=0111 1011B
通过该指令可以将操作对象的相对位设置为1
mov al, 0000 0000B
or al, 0100 0000B
执行后al=0100 0000B
将操作对象的第6位设置为1
我们可以在编程时用‘ ...... ‘的方式指定数据是以字符的形式给出的,编译器将他们转换为ASCII码
db ‘linux‘
db ‘unix‘
通过对比,我们可以看出小写字母的ASCII码的值比大写字母的大20H,十进制也就是32
可以看出除第五位外,大小写字母的其他各位都是一样的
一个字母,我们不管它之前是不是大写或者小写,我们将他的第5位置改变成0那它就变成大写字母,改为1就是小写
assume cs:code,ds:data
data segment
db ‘LINUX‘
db ‘UNIX‘
data ends
code segment
start: mov ax, data
mov ds, ax
mov bx, 0
mov cx, 5
s:mov al, [bx]
or al, 00100000B
mov [bx], al
inc bx
loop s
mov ax, 4c00H
int 21H
code ends
end start
为了更好更方便多的访问内存可以用 [bx+idata] 用bx加上一个常量来进行寻址
[bx+idata]的方式进行数组的处理
数组是在内存中一连串的区域,这个区域都是同一类型的变量
将上面程序用[bx+idata]修改,将’basic‘大写
assume cs:code,ds:data
data segment
db ‘LINUX‘
db ‘basic‘
data ends
code segment
start: mov ax, data
mov ds, ax
mov bx, 0
mov cx, 5
s:mov al, [bx]
or al, 00100000B
mov [bx], al
mov al, [bx+5]
and al, 11011111B
mov [bx+5], al
inc bx
loop s
mov ax, 4c00H
int 21H
code ends
end start
[bx+idata]的方式为高级语言实现数组提供了变利的条件
SI和DI和bx寄存器的功能是相近的,但是他们不能拆成两个8位的寄存器
以下s三组代码实现了相同的功能
mov bx, 0
mov ax, [bx]
mov si,0
mov ax, [si]
mov di,0
mov ax, [di]
由SI和DI 实现将字符串”helloworld“复制到它后面的数据区中 看代码
SI指向原始字符串,DI指向复制的空间,然后循环完成复制
assume cs:code,ds:data
data segment
db ‘helloworld‘
db ‘..........‘
data ends
code segment
start: mov ax, data
mov ds, ax
mov si, 0
mov di, 10
mov cx, 5
f: mov ax, [si]
mov [di], ax
add si, 2
add di, 2
loop f
mov ax, 4c00H
int 21H
code ends
end start
用[bx+idata] 简化程序
assume cs:code,ds:data
data segment
db ‘helloworld‘
db ‘..........‘
data ends
code segment
start: mov ax, data
mov ds, ax
mov si, 0
mov cx, 5
f: mov ax, [si]
mov [si+10], ax
add si, 2
loop f
mov ax, 4c00H
int 21H
code ends
end start
1.实现定义字符的大写首字母
assume cs:code,ds:data
data segment
db ‘1. edit ‘
db ‘2. file ‘
db ‘3. view ‘
db ‘4. help ‘
data ends
code segment
start: mov ax, data
mov ds, ax
mov bx, 0
mov cx, 4
s: mov al, [bx+3]
and al, 11011111B
mov [bx+3], al
add bx, 10
loop s
mov ax, 4c00H
int 21H
code ends
end start
2.实现将字符全部大写,我们需要进行4*3次的双重循环
assume cs:code,ds:data,ss:stack
data segment
db ‘1. edit ‘
db ‘2. file ‘
db ‘3. view ‘
db ‘4. help ‘
data ends
stack segment
dw 0,0,0,0,0,0,0,0 ;定义栈区,用来存放cx循环的值 16个字节
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
mov bx, 0
mov cx, 4 ;定义外层循环
s0: push cx ;将cx的值进行压栈
mov si, 3
mov cx, 4 ;定义内层循环
s: mov al, [bx+si]
and al, 11011111B
mov [bx+si], al
inc si
loop s
add bx,10
pop cx ;从栈顶弹出原来cx的值
loop s0 ;外层循环将cx减一
mov ax, 4c00H
int 21H
code ends
end start
下面的指令中,用word ptr指明了指令访问内存单元是一个字单元数据
mov word ptr ds:[0], 1
add word ptr ds:[0], 1
inc word ptr [bx]
下面的指令中,用word ptr指明了指令访问内存单元是一个字节单元数据
mov byte ptr ds:[0], 1 ;
在没有寄存器参与的内存单元访问指令中,用word ptr byte ptr显性的指出所要访问内存单元的长度是很有必要的
否则CPU无法得知所要访问的是字单元,还是字节单元
division 是除法指令 注意事项
除数:8位或者16位在寄存器中或者在内存单元中
被除数:默认放在AX 或DX和AX中
除数是8位的话 商存储在al中 余数存储到ah中
除数是16位的话 商存储在ax中 余数存储到dx中
计算10/3
assume cs:code,ds:data
data segment
db 3 ;定义除数
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, 10 ;定义被除数
mov bx, 0
div byte ptr [bx] ;指向定义的除数
mov ax, 4c00H
int 21H
;除数是8位的话 商存储在al中 余数存储到ah中
;除数是16位的话 商存储在ax中 余数存储到dx中
code ends
end start
如果除数是16位的话
assume cs:code,ds:data
data segment
db 3
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, 1 ;0000 0000 0000 0001
mov dx, 1 ;0000 0000 0000 0001
mov bx, 0
div word ptr [bx] ;这里就是dx在高位 ax在地位 0000 0000 0000 0001 0000 0000 0000 0001
;十进制65537/3
;商存在AX中
;余数存储到DX中
mov ax, 4c00H
int 21H
code ends
end start
如果除数是16位的话 被除数是32位,高16位在dx中,低16位在ax中,如上代码
dd是用来定义dword(double word)双字型数据 32个字节
dd 31415926 ;占32个字节 正常定义即可
dup是一个操作符,在汇编语言中同db dw dd一样,是由编译器处理的符号
它是配合db dw dd 符号使用的,用来数据的重复
db 3 dup(0) ;定义三个字节他们的值都是0
db 0,0,0 ;相当于这样
db 3 dup(0,1,2) ;定义九个个字节他们的值是0,1,2,0,1,2,0,1,2
db 0,1,2,0,1,2,0,1,2 ;相当于这样
assume cs:code,ds:data
data segment
db 2 dup(‘helloworld‘) ;连续定义两个以字节为单位的helloworld
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, 4c00H
int 21H
code ends
end start
assume cs:code,ds:data,es:table,ss:stack
data segment
db ‘1990‘,‘1991‘,‘1992‘,‘1993‘,‘1994‘,‘1995‘,‘1996‘,‘1997‘,‘1998‘,‘1999‘,‘2000‘
db ‘2001‘,‘2002‘,‘2003‘,‘2004‘,‘2005‘,‘2006‘,‘2007‘,‘2008‘,‘2009‘,‘2010‘ ;最近21年的年份
;计算年份的偏移地址 4*21=84 十六进制54H用53H
dd 116,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,5840 ;21年每年的收入
;计算收入的偏移地址 54H+54H=A8H 用A7H
dw 1,6,9,12,113,6,9,12,113,6,9,12,113,6,9,12,113,6,9,12,50 ;21年每年的人数
;计算人数的偏移地址 A8H+2A=D2 用D1
data ends
table segment
db 21 dup(‘year summ ne !! ‘)
table ends
stack segment
dw 8 dup(‘0‘)
stack ends
code segment
start: mov ax, data
mov ds, ax ;将ds和data挂钩
mov ax, table
mov es, ax ;将es和table挂钩
mov bx, 0 ;初始化参数
mov si, 0
mov di, 0
mov cx, 21 ;设置循环次数21次
s: mov al, ds:[bx] ;存放年份
mov es:[di], al
mov al, ds:[bx+1]
mov es:[di+1], al
mov al, ds:[bx+2]
mov es:[di+2], al
mov al, ds:[bx+3]
mov es:[di+3], al
mov ax, [bx+54H] ;存放收入
mov dx, [bx+56H]
mov es:[di+5H], ax
mov es:[di+7H], dx
mov ax, [si+0A8H] ;存放人数
mov es:[di+0AH], ax
mov ax, [bx+54H] ;存放人均收入
mov dx, [bx+56H]
div word ptr ds:[si+0A8H]
mov es:[di+0dH], ax
add bx, 4
add di, 16
add si, 2
loop s
mov ax, 4c00H
int 21H
code ends
end start
原文:https://www.cnblogs.com/immortal-mode/p/14106171.html