本次实验主要针对一些程序结构的运用。其实本次实验相对难度比较低,只需要先用高级语言写一遍再翻译成汇编就可以(因为本次实验并未涉及到某些高级语言特性)。
实验内容
(2) 根据下述情况,分别编写程序,记录 BX 中 1 的个数(需要考虑 BX 中二进制 串的特殊情况),要求如下:
⚫ 循环次数已知
⚫ 循环次数未知
(3) 按照下列要求,编写相应程序段。
1) 起始地址为 string 的主存单元中存放一个字符串(长度大于 6),把该字符串中的第 1 个和第 6 个字符(字节量)传送给 DX 寄存器;
2) 从主存 buffer 开始的 4 字节中保存了 4 个非压缩 BCD 码,现按低(高) 地址对低(高)位的原则,将他们合并到 DX 中。
3) 假设从 B800H:0 开始存放有 100 个 16 位无符号数,编程求它们的和,并 存在 DX.AX 中
4) 一个 100 字节元素的数组首地址为 array,将每个元素减 1(不考虑溢出)。
(4) 把内存中从 PACKED 开始的 10 个字节单元中的 16 位压缩 BCD 数转换成非压 缩 BCD 数,并把结果存放在 UNPACKED 开始的 20 个字节单元中;将下列代 码补充完整,并且自己定义 PACKED 中的数据,将 UNPACKED 中的结果展示 出来。 MOV DX, _____ MOV CL, ______ MOV SI, 0 MOV DI, ___ CONVERT: MOV AL, [SI+PACKED] MOV AH, AL AND AL, 0FH __________ MOV [DI+UNPACKED], ____ ADD DI, ____ ______ DEC DX JNZ CONVERT
(5) 给定一个有序数组(均小于 FFH 例如 02H, 07H, 0BH, 0FH, 13H, 1CH, 24H, 39H, 40H, 57H, 68H)和一个目标值(例如 79H),请判断数组中是否含有两个数的 和为目标值,请设计一个算法,将时间复杂度控制在 O(n),编程实现并验证 你的算法。
实验可能遇见的问题
(2)要求自行别写一个程序循环对BX进行操作,可以简单地写个对BX进行移位的实验。
比如本人写的是当BX小于某个数时停止循环,这就是一个未知次数的循环,使用JMP和JCC控制。
try: shr bx,1
cmp bx,1000
jb next
jmp try
next: ...
(3)
2)可以使用移位指令和OR指令进行压缩。例如:
.model small
.data
buffer dw 0009h,0008h,0007h,0006h
.stack
.code
.startup
mov ax,buffer
mov cl,12
shl ax,cl
mov si,2
mov dx,buffer[si]
mov cl,8
shl dx,cl
or ax,dx
add si,2
mov dx,buffer[si]
mov cl,4
shl dx,cl
or ax,dx
add si,2
mov dx,buffer[si]
or ax,dx
mov dx,ax
.exit
end
注意CL的向左移位次数。当然,这个程序相对臃肿,但是理解起来很简单。
3)你可以循环初始化所有数据(或者干脆不初始化),直接写求和代码。
(4)不多废话,直接看代码。
.MODEL SMALL
.DATA
PACKED dw 0123h,1234h,2345h,6789h,7890h
unpacked dw 10 dup(?)
.STACK
.CODE
.STARTUP
mov dx,10 ;设置循环次数
mov cl,4 ;循环移位位数为4
mov si,0
mov di,0 ;起始偏移量为0
convert:mov al,byte ptr[si+packed]
mov ah,al
and al,0fh
shr ah,cl ;高四位要移到低四位
mov [di+unpacked],ax ;整个字传送
add di,2 ;对应非压缩要移动2字节
mov ax,0
inc si
dec dx ;压缩移动1字节
jnz convert
.EXIT
END
(5)这是双指针算法的汇编实现。网上查下C语言的对撞指针实现,然后翻译成汇编即可。
;双指针算法汇编实现
;如果可以输出两个数,不可以输出空
.MODEL SMALL
.DATA
array db 02h,07h,0bh,0fh,13h,1ch,24h,39h,40h,57h,68h
target db 37h
.STACK
.CODE
.STARTUP
lea bp,array ;bp左指针
lea bx,array+sizeof array-1 ;bx右指针
try:mov al,[bp]
add al,[bx]
cmp al,target ;比较bp+bx和target
jb bpp ;若小于,则bp++
jz quit ;若等于,则输出
dec bx
cmp bx,bp
jb ending ;大于target时,bx--,当bx小于bp,说明找不到
jmp try ;继续比较
bpp:inc bp
cmp bp,bx
jnbe ending ;当bp大于bx,说明找不到,直接退出
jmp try ;继续比较
quit:
mov dl,[bp]
mov cl,4
shr dl,cl
add dl,30h
mov ah,2
int 21h
mov dl,[bp]
and dl,0fh
add dl,30h
mov ah,2
int 21h
mov dl,10
mov ah,2
int 21h
mov dl,[bx]
shr dl,cl
add dl,30h
mov ah,2
int 21h
mov dl,[bx]
and dl,0fh
add dl,30h
mov ah,2
int 21h
mov dl,10
mov ah,2
int 21h
ending:
mov ah,4ch
int 21h
.EXIT
END
上面代码看起来很长的原因主要是控制输出格式导致的(你看到下面很多mov ah,2 /int 21h)。
总结:
上面代码不是最简洁的形式,你可以使用一些高级的伪指令写出更简洁的代码惊艳你的老师(但是并没有什么用),本文除了变量定义伪指令和简化段定义,其他几乎都使用硬指令来完成。虽然并不高效,但胜在好懂。欢迎各位有更好的想法指正。