吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 2247|回复: 5

[汇编] 8086汇编-程序设计

[复制链接]
啥都不会 发表于 2022-8-15 01:35 | 显示全部楼层 |阅读模式

本帖最后由 啥都不会 于 2022-8-15 10:10 编辑

前言:
这篇笔记主要学习8086汇编程序设计。参考自 "杨季文《80x86汇编语言程序设计》"

每个人的思路想法都是不一样的,不建议大家照着我写的代码抄。不论用什么语言,写代码只是将我们的思路以代码的形式写出来。因此在写代码之前,要先把思路、算法、程序逻辑结构图都理出来,不然直接蒙头写代码很容易出错。
编程语言:
汇编语言

以下为主题内容:

顺序程序设计
使用汇编些顺序程序时,要注意指令的先后顺序,写代码时有些指令顺序可以前后颠倒,有些则不行。此外,还需要注意顺序的优化,充分利用前面指令的处理结果,尽量避免重复操作。

例1
设 X 和 Y 均为16位无符号数,写一个求表达式 16X+Y 值的程序。

程序逻辑结构图
183583181-5328708d-a3e4-4029-83d2-df0795dde1b8.png

加法运算

[Asm] 纯文本查看 复制代码
;程序名:T3-2.asm
;算法1:加法运算
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数)。
DESG SEGMENT
X DW  2345H
Y DW  5678H
Z DD  ?
DESG    ENDS

CSEG SEGMENT
    ASSUME  cs:CSEG,ds:DESG
start:
    mov AX,DESG
    mov DS,AX
    mov AX,X
    xor DX,DX
    add AX,AX   ;x * 2
    adc dx,dx
    add ax,ax   ;x * 4
    adc dx,dx
    add ax,ax   ;x * 8
    adc dx,dx
    add ax,ax   ;x * 16
    adc dx,dx
    add ax,Y  ;在 x*16的结果上加上y
    adc dx,0
    mov word ptr Z,ax
    mov word ptr Z+2,dx

    mov ax,4c00h
    int 21h
CSEG ENDS
     END start


移位法

[Asm] 纯文本查看 复制代码
;程序名:T3-2-1.asm
;算法2:移位法
;程序结构:顺序结构
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数),使用移位法运算。
DESG SEGMENT
XXX DW  2345H
YYY DW  5678H
ZZZ DD  ?
DESG    ENDS

CSEG SEGMENT
    ASSUME  cs:CSEG,ds:DESG
start:
    mov AX,DESG
    mov DS,AX
    mov ax,xxx
    mov dl,ah
    ;这两段指令操作是一样的,只不过一个是手写4次;另一个是让CPU自行循环重复执行4次。
    ;shl ax,1
    ;adc dx,0
    ;shl ax,1
    ;adc dx,0
    ;shl ax,1
    ;adc dx,0
    ;shl ax,1
    ;adc dx,0
    mov cx,4
    shl ax,cl
    shr dx,cl
    mov bx,yyy
    add ax,bx
    mov word ptr zzz,ax
    mov word ptr zzz+2,dx
    ;
    mov ax,4c00h
    int 21h
CSEG ends
    end start



乘法指令


[Asm] 纯文本查看 复制代码
;程序名:T3-2-2.asm
;算法3:乘法运算
;程序结构:顺序结构
;功能:计算 16X+Y(X 和 Y 均为 16 位无符号数),使用mul指令。
DESG SEGMENT
XXX DW  2345H
YYY DW  5678H
ZZZ DD  ?
result dw 0,0
db 24h
DESG    ENDS

CSEG SEGMENT
    ASSUME  cs:CSEG,ds:DESG
start:
    mov AX,DESG
    mov DS,AX
    mov ax,16
    ;
    ;mov bx,xxx
    ;mul bx
    mul xxx
    ;
    ;mov cx,yyy
    ;add ax,cx
    add ax,yyy
    adc dx,0
    mov word ptr zzz,ax
    mov word ptr zzz+2,dx
    ;
    mov ax,4c00h
    int 21h
CSEG ends
    end start


代码越短并不意味着执行速度越快,因为一条乘除法指令所花的时间较多。当乘数是2的倍数时,往往可使用移位指令实现乘法运算;当乘数较小时,往往可采用加法实现乘法运算;对执行速度要求不大的情况下,可直接使用乘法指令实现乘法运算。

例2
把压缩存放的 8421 BCD码,转换为对应十进制数字 ASCII 码的程序。

8421 BCD码就是,将4位二进制数,转换为1位十进制的编码方式
183588205-bba2f618-43ad-4efb-9634-7560424f1d0e.png

所谓压缩存放是指一个字节中存放两个BDC码,即低4位存放一个BCD码,高4位存放一个BCD码。如果仅仅低4位存放一个BCD码,就称为非压缩BCD码。


算法1

1. 程序逻辑结构图
184138033-d4b6d4fd-8304-4633-8eb8-a05d36cd54c5.png

2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-3.asm
;功能:把压缩存放的 8421 BCD码,转换为对应十进制数字 ASCII 码的程序。
;算法1:使用左移+与运算
assume cs:code,ds:data

data segment
number db 12h
result db 0,0,'$'
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov al,number
    mov cl,4
    shr al,cl
    add al,30h
    mov result,al
    mov al,number
    and al,0fh
    add al,30h
    mov result+1,al
    ;
    mov dx,offset result
    mov ah,9
    int 21h
    ;
    mov ax,4c00h
    int 21h
code ends
end start



算法2

1. 程序逻辑结构图
184140556-37dfd52e-8f0e-430e-a0e4-ae2fe9b3b0ac.png

2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-3-1.asm
;功能:把压缩存放的 8421 BCD码,转换为对应十进制数字 ASCII 码的程序。
;算法2:使用循环右移+右移
assume cs:code,ds:data

data segment
number db 12h
result dw 0
db '$'
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    xor ax,ax
    mov al,number
    mov cl,4
    ror ax,cl
    shr ah,cl
    add ax,3030h
    mov result,ax
    ;
    mov dx,offset result
    mov ah,9
    int 21h
    ;
    mov ax,4c00h
    int 21h
code ends
end start


注意:ah是高4位,al是低4位,计算机输出是从低内存数到高内存数打印。即低4位是31h,高4位是32h


例3
把 16 进制数转换成七段数码管

程序逻辑结构图
184163343-487dd57c-20ce-42c0-9650-87b7bfe0b109.png

查表法

[Asm] 纯文本查看 复制代码
;程序名:T3-4.asm
;功能:把 16 进制数转换成七段数码管并输出
;============================================
;算法一:查表法(类似于数组)
assume cs:code,ds:data

data segment
tab db 1000000B,1111001B,0100100B,0110000B
    db 0011001B,0010010B,0000010B,1111000B
    db 00000000B,0010000B,0001000B,0000011B
    db 1000110B,0100001B,0000110B,0001110B
number db 0
result db 0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    xor bx,bx
    mov bx,number
    ;
    mov dl,tab[bx]
    mov ah,2
    int 21h
    ;
    mov ax,4c00h
    int 21h

code ends
    end start



查表指令


[Asm] 纯文本查看 复制代码
;程序名:T3-4-1.asm
;功能:把 16 进制数转换成七段数码管并输出
;============================================
;方法二:查表指令xlat
assume cs:code,ds:data

data segment
tab db 1000000B,1111001B,0100100B,0110000B,0011001B,0010010B,0000010B,1111000B,00000000B,0010000B,0001000B,0000011B,1000110B,0100001B,0000110B,0001110B
number db 0
result db 0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov bx,offset tab   ;bx为首地址
    mov al,number       ;al为偏移地址
    and al,0fh          ;number 最大值是 F(16)
    xlat                ;取出偏移地址(al)的值,传给al寄存器
    ;
    mov dl,al
    mov ah,2
    int 21h
    ;
    mov ax,4c00h
    int 21h

code ends
    end start


例4
设X是一个1~10之间的整数,写一个求函数Y=LG(X)值的程序。

程序逻辑结构图
184292583-578c81bf-ba03-49a4-a76b-5f395139f2b1.png

代码

[Asm] 纯文本查看 复制代码
;程序名:T3-5.asm
;例4:设X是一个1~10之间的整数,写一个求函数Y=LG(X)值的程序。
;求1~10的对数值,以10为底的对数在0~1之间,为了表示方便和考虑精度,对数值放大10000倍。

assume cs:code,ds:data

data segment
VLAUE DB 4
ANSWER DW ?
TAB DW 0,3010,4771,6021,6990,7782,8451,9031,9542,10000  ;对数表
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    xor ax,ax
    mov al,VLAUE
    dec ax
    add ax,ax
    mov bx,ax
    mov ax,TAB[bx]
    mov ANSWER,ax
    mov ax,4c00h
    int 21h
code ends
    end start


分支程序设计

例1

实现三个无符号数的有大到小的排序

程序逻辑结构图
184307495-45510e79-403e-4be8-b390-7b18f9a5be5d.png

寄存器数据交换

[Asm] 纯文本查看 复制代码
;程序名:T3-6.asm
;功能:实现三个无符号数的有大到小的排序
;方法一:使用寄存器实现数据交换
assume cs:code,ds:data

data segment
buffer db 87,234,123
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov si,offset buffer
    mov al,[si]
    mov bl,[si+1]
    mov cl,[si+2]
    cmp al,bl
    jae next1
    xchg al,bl
next1:
    cmp al,cl
    jae next2
    xchg al,cl
next2:
    cmp bl,cl
    jae next3
    xchg bl,cl
next3:
    mov [si],al
    mov [si+1],bl
    mov [si+2],cl
    mov ax,4c00h
    int 21h
code ends
    end start



内存数据交换


[Asm] 纯文本查看 复制代码
;程序名:T3-6-1.asm
;功能:实现三个无符号数的有大到小的排序
;方法二:使用内存实现数据交换
assume cs:code,ds:data

data segment
buffer db 87,123,234
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov al,buffer[si]
    cmp al,[si+1]
    jae next1
    xchg al,[si+1]
    xchg [si],al
next1:
    mov al,buffer[si]
    cmp al,[si+2]
    jae next2
    xchg [si+2],al
    xchg [si],al
next2:
    mov ax,[si+1]
    cmp al,ah
    jae next3
    xchg al,ah
    mov [si+1],ax
next3:
    mov ax,4c00h
    int 21h
code ends
    end start



例2
实现把一个十六进制数转换为对应的 ASCII 码的程序。

程序逻辑结构图
184311493-661de37b-c96a-4912-96e7-423a51215e98.png

算法1


[Asm] 纯文本查看 复制代码
;程序名:T3-7.asm
;功能:实现把一个十六进制数转换为对应的 ASCII 码的程序。
;方法一:分开计算,数字+30h,字母+37h
assume ds:data,cs:code

data segment
number db 0Fh
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov al,number
    and al,0fh
    cmp al,0ah
    jb num_add
    add al,37h
    mov dl,al
    jmp output
num_add:
    add al,30h
    mov dl,al
output:
    mov ah,2
    int 21h
    mov ax,4c00h
    int 21h
code ends
end start


算法2

[Asm] 纯文本查看 复制代码
;程序名:T3-7-1.asm
;功能:实现把一个十六进制数转换为对应的 ASCII 码的程序。
;方法二:分开计算,如果是字母+7h,再加30h;如果是数字+30h
assume ds:data,cs:code

data segment
number db 0Fh
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov al,number
    and al,0fh
    cmp al,0ah
    jb num
    add al,7
num:
    add al,30h
    mov dl,al
output:
    mov ah,2
    int 21h
    mov ax,4c00h
    int 21h
code ends
end start



例3
写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。

方法1
存入一个 ASCII,先判断是否为数字(是 -30h),再判断是否为大写字母(是 -37h),再判断是否为小写字母(是 -57h),最后输出结果。

1. 程序逻辑结构图
184326124-7bc8d3fc-0f37-44a0-88ed-e5d15981b622.png

2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-8.asm
;功能:写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。如果要转换的ASCII码没有对应的十六进制码,则转换为特殊值负1
assume ds:data,cs:code

data segment
ascii db '$'
err db '-','1','$'
data  ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov dl,ascii
    cmp dl,'0'
    jb error
    cmp dl,'9'
    ja char_A
    sub dl,30h
    jmp output
char_A:
    cmp dl,'A'
    jb error
    cmp dl,'F'
    ja char_aa
    sub dl,37h
    jmp output
char_aa:
    cmp dl,'a'
    jb error
    cmp dl,'f'
    ja error
    sub dl,57h
    jmp output
error:
    xor dh,dh
    mov dh,-1
output:
    cmp dh,-1
    jz char_error
    cmp dl,9
    ja char
    add dl,30h
char:
    add dl,37h
    ;
    mov ah,2
    int 21h
    jmp stop
char_error:
    mov dx,offset err
    mov ah,9
    int 21h
stop:
    mov ax,4c00h
    int 21h
code ends
end start


这段代码的问题是,一直在重复判断,重复运算。写了很多冗余代码

方法2

1. 程序逻辑结构图
184475617-c4b111fa-8705-4c17-9344-6c97d6064ce6.png

2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-8-1.asm
;功能:写一个实现把一位十六进制数所对应的 ASCII 码转换为十六进制数的程序。
assume ds:data,cs:code

data segment
ascii db 'g'
err db '-','1','$'
data  ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov dl,ascii
    sub dl,30h
    cmp dl,9
    jbe output
    cmp dl,0f0h
    ja error
char_a:
    sub dl,7
    cmp dl,0ah
    jb error
    cmp dl,0fh
    jbe output
    cmp dl,0f0h
    ja error
char_AA:
    sub dl,20h
    cmp dl,0ah
    jb error
    cmp dl,0fh
    jbe output
    jmp error
output:
    mov dl,ascii
    mov ah,2
    int 21h
    jmp stop
error:
    mov al,0ffh
    mov dx,offset err
    mov ah,9
    int 21h
stop:
    mov ax,4c00h
    int 21h
code ends
end start



循环程序设计

例1
求内存中从地址 0040:0000H 开始的 1024 个字的字校验和。

程序逻辑结构图
184476304-620da488-cbf6-4c8b-bab0-930d16ab5e66.png

代码

[Asm] 纯文本查看 复制代码
;程序名:T3-9.asm
;功能:求内存中从地址 0040:0000H 开始的 1024 个字的字校验和。
assume cs:code,ds:data

data segment
sum dw 0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov ax,0040h
    mov es,ax
    ;
    xor ax,ax
    mov cx,1024
summer:
    add ax,es:[si]
    add si,2
    loop summer
    mov sum,ax
    mov ax,4c00h
    int 21h
code ends
end start



例2
不使用乘法实现乘法运算

累加法

1. 程序逻辑结构图
184476849-261ff1d1-7bd2-4095-aea0-0a1fd549875a.png

2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-10.asm
;功能:不使用乘法实现乘法运算(累加法)

assume ds:data,cs:code

data segment
x db 234    ;被乘数
y db 125    ;乘数
z dw 0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov al,x
    xor ah,ah
    mov cl,y
    xor ch,ch   ;设置循环次数
    xor dx,dx
muls:
    add dx,ax
    loop muls
    mov z,dx
stop:
    mov ax,4c00h
    int 21h
code ends
end start



位移相加法

1. 程序逻辑结构图
184479390-649b153e-a482-47af-a8ab-adb3ff83fc79.png


2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-10-1.asm
;功能:不使用乘法实现乘法运算(位移相加法)
;例:AX(乘数)、bl(被乘数),dx(乘积)
;此时 bl=4=0100,ax=12=2^0, dx=0
;bl 右移1位,发现是0,也就是被乘数比2^0大
;既然被乘数不是2^0,那有可能是2^1,那么 ax 提前累加,ax=ax+ax=24
;bl 右移1位,发现是0,也就是被乘数比2^1大
;那么 ax 提前累加,ax=ax+ax=48
;bl 右移1位,发现是1,也就是被乘数包含2^2,那么 dx(乘积) = ax+dx=48
;就这样,循环8次,只要 bl 的 bit 位是1,ax的累加值就放到乘积dx中;反之ax继续累加,直到循环结束

assume ds:data,cs:code

data segment
x db 234    ;被乘数
y db 125    ;乘数
z dw 0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov al,x
    xor ah,ah
    mov bl,y
    xor dx,dx
    mov cx,8    ;按位相加运算,两个都是 8 位的值
muls:
    shr bl,1
    JNC next    ;乘数右移一位,如果溢出说明该值是1
    add dx,ax   ;溢出 dx=dx+ax
next:
    add ax,ax   ;没有溢出 ax*2
    loop muls
    mov z,dx
stop:
    mov ax,4c00h
    int 21h
code ends
end start


例3
把一个16位二进制数转换为一个5位十进制数,并输出。


程序逻辑结构图
184506485-236ebfe3-5794-4468-b8b3-d6d98707fdff.png

循环中有这行代码 mov ax,dx,当时考虑到 “被除数不能是0”,所以把第一次计算排除在循环中。


代码

[Asm] 纯文本查看 复制代码
;程序名:T3-11.asm
;功能:把一个16位二进制数转换为一个5位十进制数,并输出。
;算法:假设X为12345,除以 10000,1000,100,10,1 获取商进行输出
assume ds:data,cs:code

data segment
number dw 0ABCDh
result db 0,0,0,0,0,'$'
jm dw 10000,1000,100,10,1
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov ax,number
    mov bx,0
    push bx
    xor dx,dx
    xor si,si
    mov cx,4
    ;
    mov bx,jm[si]
    div bx
    add ax,30h
    pop bx
    mov result[bx],al
    add si,2
    inc bx
    push bx
divs:
    mov ax,dx
    xor dx,dx
    mov bx,jm[si]
    div bx
    add ax,30h
    pop bx
    mov result[bx],al
    add si,2
    inc bx
    push bx
    loop divs
    ;
    mov dx,offset result
    mov ah,9
    int 21h
    ;
    mov ax,4c00h
    int 21h
code ends
    end start


优化1
利用di作为循环次数,cx作为除数,bx和si存储偏移地址,同时把 “divs” 标号,上面一段代码去掉。


去掉第一段代码的方法:把原始的 “被除数” 作为 “余数” 看待,提前把这个值传给dx。

[Asm] 纯文本查看 复制代码
;程序名:T3-11-1.asm
;功能:把一个16位二进制数转换为一个5位十进制数,并输出。
;算法:假设X为12345,除以 10000,1000,100,10,1 获取商进行输出
;优化1:不使用loop 指令,可优化掉大多数重复指令
assume ds:data,cs:code

data segment
number dw 0ABCDh
result db 0,0,0,0,0,'$'
jm dw 10000,1000,100,10,1
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov ax,number
    lea bx,jm
    lea si,result
    ;初始化
    mov dx,ax   ;备份要转换的值
    mov di,si
    add di,5    ;定义循环次数
L1:
    mov ax,dx   ;每次循环将余数传给ax
    xor dx,dx   ;div使用 DX:AX 除以16位,需要将dx置为0(被除数扩展)
    ;div指令除以16位,商在ax中,余数在dx中
    mov cx,[bx]
    div cx
    add al,30h
    mov [si],al
    inc si
    add bx,2
    cmp si,di
    jnz L1
    sub si,5
    ;
    mov dx,offset result
    mov ah,9
    int 21h
    ;
    mov ax,4c00h
    int 21h
code ends
    end start



优化2
之前是利用商作为结果来存储,这里使用余数作为结果来存储。这种方法大大减少了代码,不需要再去到内存中一一读取除数。

写代码时,多换几种思路会减少很多麻烦。同时你所理解的知识多少,也影响写代码的思路。

[Asm] 纯文本查看 复制代码
;程序名:T3-11-2.asm
;功能:把一个16位二进制数转换为一个5位十进制数,并输出。
;算法:假设X为12345,每次循环除以 10,获取余数进行输出
;优化2:使用余数来处理,省掉除数列表
assume cs:code,ds:data

data segment
number dw 0ABCDh
result db 0,0,0,0,0,'$'
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
    mov di,5
    mov cx,10
    mov ax,number
L1:
    xor dx,dx
    div cx
    add dl,30h
    mov result[di-1],dl     ;用di判断循环,但是存储结果di需要减1
    dec di
    jnz L1
    ;
    lea dx,result
    mov ah,9
    int 21h
    mov ax,4c00h
    int 21h
code ends
end start



例4
把一个字符串中的所有大写字母改写成小写。

程序逻辑结构图
184507752-b3ef3f7b-36ce-46d9-af89-da8a8c60682e.png

代码

[Asm] 纯文本查看 复制代码
;程序名:T3-12.asm
;功能:把一个字符串中的所有大写字母改写成小写。

assume ds:data,cs:code

data segment
char db 'HOW are yoU !',0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
char_A:
    mov dl,char[si]
    cmp dl,0
    jz stop
    ;
    cmp dl,41h
    jb output
    cmp dl,5Ah
    ja output
    add dl,20h
    ;
output:
    inc si
    mov ah,2
    int 21h
    jmp char_A
    ;
stop:
    mov ax,4c00h
    int 21h
code ends
    end start



例5
判定从地址 0040:0000H 开始的 2048 个内存字节单元中是否有字符 'A'。
如有则把第一个(按地址由小到大为序)含此指定字符的存储单元的地址偏移送到  0000:03FEH 单元中
如果没有把特征值 0FFFFH 送到 0000:03FEH 单元

程序逻辑结构图
184508096-386cf607-7836-4b65-b88c-eed958b4477a.png

代码

[Asm] 纯文本查看 复制代码
;程序名:T3-13.asm
;功能:判定从地址 0040:0000H 开始的 2048 个内存字节单元中是否有字符 'A'。
;如有则把第一个(按地址由小到大为序)含此指定字符的存储单元的地址偏移送到  0000:03FEH 单元中
;如果没有把特征值 0FFFFH 送到 0000:03FEH 单元

assume cs:code
;常量定义
segaddr = 40h   ;源地址段值
offaddr = 0     ;源地址偏移
count = 2048    ;长度(计数)
keychar = 'A'   ;指定字符
segresu = 0     ;目的保存单元段值
offresu = 03FEh ;目的保存单元偏移

code segment
start:
    mov ax,segaddr
    mov ds,ax
    mov ax,offaddr
    mov si,ax
    mov ax,segresu
    mov es,ax
    mov ax,offresu
    mov di,ax
    mov cx,count
    mov ah,keychar
    ;
find:
    mov al,[si]
    cmp ah,al
    jnz loops
    inc di
    mov [di],si
loops:
    inc si
    loop find
    mov di,03FEh
    mov dh,[di]
    cmp dh,ah
    jz stop
    mov dx,-1
    mov [di],dx
stop:
    mov ax,4c00h
    int 21h
code ends
    end start



例6

设缓冲区 DATA 中有一组单字节有符号数,以0为结束标志。把前5个正数依次送入缓冲区 PDATA,把前 5 个负数依次送入缓冲区MDATA;如正数或负数不足5个,则用 0 补足。

程序逻辑结构图
184508831-9ea4aa48-94b0-4b86-afc3-51d03da0a6f2.png

代码

[Asm] 纯文本查看 复制代码
;程序名:T3-14.asm
;功能:设缓冲区 DATA 中有一组单字节有符号数,以0为结束标志。
;程序功能:把前5个正数依次送入缓冲区 PDATA,把前 5 个负数依次送入缓冲区MDATA;如正数或负数不足5个,则用 0 补足

assume cs:code,ds:data

data segment
DATA1 db 1,2,-1,3,-4,-5,0
PDATA db 0Ch,0Ch,0Ch,0Ch,0Ch
MDATA db 0Ch,0Ch,0Ch,0Ch,0Ch
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    mov es,ax
    ;
    mov cx,10
    xor bx,bx
mnum:
    mov al,DATA1[si]
    cmp al,0
    jz supp1
    and al,80h
    cmp al,0
    jnz pnum
    mov al,DATA1[si]
    mov MDATA[di],al
    inc di
    inc si
    loop mnum
    jmp supp1
pnum:
    mov al,DATA1[si]
    mov PDATA[bx],al
    inc bx
    inc si
    loop mnum
supp1:
    mov ax,5
    sub ax,di
    jz supp2
    mov cx,ax
P0:
    mov PDATA[di],0
    inc di
    loop P0
supp2:
    mov ax,5
    sub ax,bx
    jz stop
    mov cx,ax
m0:
    mov MDATA[BX],0
    inc bx
    loop m0
stop:
    mov ax,4c00h
    int 21h
code ends
    end start


例7
设 BUFFER 缓冲区中有10各单字节无符号整数,写一个程序将他们由小到大排序

算法1

1. 程序逻辑结构图
184524550-a6ae23e5-134e-4910-b447-4186e296c82d.png

2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-15.asm
;功能:说明二重循环的实现
;算法:简单选择法
assume cs:cseg,ds:dseg

dseg segment
;buffer db 23,12,45,32,127,3,9,58,81,72
number db 4,1,6,0,3,2,9,8,7,5
N EQU 10
dseg ends

cseg segment
start:
    mov ax,dseg
    mov ds,ax
    mov bx,offset number-1
    mov si,1
forI:
    mov di,si
    inc di
forJ:
    mov al,[bx+si]
    cmp al,[bx+di]
    jbe nextJ
    xchg al,[bx+di]
    mov [bx+si],al
nextJ:
    inc di
    cmp di,N
    jbe forJ
nextI:
    inc si
    cmp si,N-1
    jbe forI
    ;
    xor si,si
    mov cx,10
print:
    mov dl,number[si]
    add dl,30h
    mov ah,2
    int 21h
    inc si
    loop print
    ;
    mov ax,4c00h
    int 21h
cseg ends
end start



算法2

1. 程序逻辑结构图
184540841-604f2126-7252-4a36-832f-653c4ae19839.png

2. 代码
[Asm] 纯文本查看 复制代码
;程序名:T3-15-2.asm
;功能:设 BUFFER 缓冲区中有10各单字节无符号整数。
;算法一:冒泡排序
assume cs:code,ds:data

data segment
number db 3,4,6,5,7,8,1,2,0,9
;3,4,5,6,7,1,2,0,8,9
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    ;
L0:
    mov cx,9
L1:
    sub cx,bx               ;BX 表示外循环次数
    jz output               ;外循环结束后,结束程序
L2:
    inc si
    mov al,number[si-1]
    cmp al,number[si]       ;第一个数(a)和第二个数(b)进行比较
    jnb move                ;如果 a>b,交换数据
    dec cx                  ;循环次数-1
    jz reset                ;内循环结束后,初始化数据,准备外循环
    jmp L2                  ;不交换数据,继续内循环
move:
    xchg al,number[si]
    mov number[si-1],al
    loop L2                 ;交换数据,继续内循环
reset:
    inc bx
    xor si,si
    jmp L0
output:
    xor si,si
    mov cx,10
print:
    mov dl,number[si]
    add dl,30h
    mov ah,2
    int 21h
    inc si
    loop print
    ;
    mov ax,4c00h
    int 21h
code ends
end start


例8

分别有两个以0结尾的字符串在不同的数据段中。如果数据段1的字符串,包含了数据段2的字符串,flag变量置为1,否则将其清0。

程序逻辑结构图
184541231-43ae9fca-eb8d-4102-b93a-27bb3d112891.png

代码

[Asm] 纯文本查看 复制代码
;程序名:T3-16.asm
;功能:分别有两个以0结尾的字符串在不同的数据段中。如果数据段1的字符串,包含了数据段2的字符串,flag变量置为1,否则将其清0。
assume cs:code1,ds:data1,es:data2

data1 segment
char1 db 'welcome to masm!',0
data1 ends

data2 segment
char2 db 'masm',0
len = ($ - char2)-1
flag db 0
data2 ends


code1 segment
start:
    mov ax,data1
    mov ds,ax
    mov ax,data2
    mov es,ax
    ;
    mov cx,len-1
not_find:
    xor di,di
    mov bl,char1[si]
    cmp bl,0
    jz stop
    mov al,char2[di]
    cmp al,bl
    jz find
    inc si
    jmp not_find
find:
    inc si
    mov bl,char1[si]
    inc di
    mov al,char2[di]
    cmp al,bl
    jnz not_find
    loop find
    mov flag,1
stop:
    mov ax,4c00h
    int 21h
code1 ends
end start


评分

参与人数 10HB +13 THX +5 收起 理由
花盗睡鼠 + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
消逝的过去 + 1
今日下雨 + 1
leeairw + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
后学真 + 1 [吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意!
龍自在 + 1
sjtkxy + 1 + 1
小声点我布隆 + 2 + 1 [吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少!
192939 + 4 + 1
zxjzzh + 2 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
小声点我布隆 发表于 2022-8-15 20:38 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
sjtkxy 发表于 2022-9-30 05:25 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
龍自在 发表于 2022-10-7 15:20 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
后学真 发表于 2022-10-7 16:00 | 显示全部楼层

程序设计,难度很高,谢谢老师分享
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
吾爱稀饭 发表于 2022-10-11 23:26 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层
4层
5层
6层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表