MODEL SMALL
DATA
X1 DB '1234567890123456' ; 16位的十进制被加数
X2 DB '9233445566778899' ; 16位的十进制加数
Y1 DB '00000000000000000' ; 17位的十进制加法的和(考虑最高位可能有进位产生)
CODE
STARTUP
LEA SI, X1
LEA DI, X2
LEA BX, Y1
ADD SI, 15 ; SI 指向被加数的最右端的个位数
ADD DI, 15 ; DI 指向加数的个位数
ADD BX, 16 ; BX 指向加法的和的个位数
MOV CX, 16 ; 循环16次
CLC ; 运算前将CF清0
PUSHF ;PSW标志寄存器入栈保存
AGAIN:
POPF ; PSW标志寄存器出栈,恢复CF
MOV AL, [SI] ;取被加数到AL
ADC AL, [DI] ;将加数加到AL中
AAA ;非压缩的BCD码(即ASCII码)加法调整
MOV [BX], AL ; 保存加得的和
PUSHF ; PSW标志寄存器入栈,主要是为了保存好CF标志
AND BYTE PTR [BX], 0FH ;将这一位加法的和的高4位清零
ADD BYTE PTR [BX], 30H ; 将这一位加法的和调整成数字的ASCII码
DEC SI ; 调整指针,处理下一位
DEC DI
DEC BX
LOOP AGAIN
POPF ; 这一小段指令处理最后的进位形成的第17位
MOV AL, 0
ADC AL, 0
ADD AL, 30H
MOV [BX], AL
EXIT
END
程序说明:
1 很长的整数,直接按每一位用一个字节的数字字符的ASCII码存储,16位的十进制数就是一个由16个数字字符构成的字符串
2 加法运算,是将每个ASCII字符看成是非压缩的BCD码,在AL中进行过加法运算后,用非压缩的BCD码调整指令将结果调整成非压缩的BCD码格式,加法的进位保存在CF中。运算规则完全按照手工计算的方法进行,依个位、十位、百位……的次序从右向左逐位相加,在相加时带上上一位的进位。程序共循环16次。
3 为了避免指针调整和循环控制时CF被这些运算结果所修改,造成运算结果错误,需要用堆栈保存PSW的方法保护CF,运算结果调整好以后立即保存CF,下次运算前恢复CF。
4 程序只考虑了运算,没有考虑显示。可以在调试程序中查看运算结果是否正确。若需要加上显示功能,对数据段的定义稍加修改,用09H号DOS系统功能调用即可。
1、编两个通用过程完成将AX中存放的二进制数转换成压缩型BCD码以及将BCD码转换成二进制数。
; 本程序通过编译,运行正确。
Code Segment
Assume CS:Code,DS:Code
; -----------------------------------------
; 功能:将AX中的二进制数转换成压缩型BCD码
; 入口:AX=16位二进制数(因为压缩BCD码最大为:9999H,所以,AX的二进制值不能大于270FH)
; 出口:AX=转换后的压缩型BCD码
Binary_BCD Proc Near
push dx
push cx
push bx
push di
mov @@Temp_Save,0
mov @@Temp_Save[2],0 ;将临时两个字存储单元置0
mov bx,10
lea di,@@Temp_Save[3]
cld
@@Divide: xor dx,dx
div bx
mov [di],dl ;保存余数
dec di
test ax,0ffffh
jnz @@Divide
mov cl,4
mov ax,@@Temp_Save[2]
xchg ah,al
shl al,cl
shl ax,cl
mov dl,ah
mov ax,@@Temp_Save
xchg ah,al
shl al,cl
shl ax,cl
mov al,dl
pop di
pop bx
pop cx
pop dx
ret
@@Temp_Save dw 2 dup()
Binary_BCD EndP
; -----------------------------------------
; 功能:将AX中的压缩型BCD码转换成二进制数
; 入口:AX=压缩型BCD码
; 出口:AX=转换后的16位二进制数
BCD_Binary Proc Near
push dx
push cx
push bx
mov dx,ax
mov bx,10
mov cl,4
shr ah,cl
xchg ah,al
cbw
push dx
mul bx
pop dx
and dh,0fh
xchg dh,dl
push dx
xor dh,dh
add ax,dx
mul bx
pop dx
xchg dh,dl
xor dh,dh
push dx
shr dx,cl
add ax,dx
mul bx
pop dx
and dl,0fh
add ax,dx
pop bx
pop cx
pop dx
ret
BCD_Binary EndP
; -----------------------------------------
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
mov ax,3456
call Binary_BCD ;将AX中的二进制数转换成压缩型BCD码
call BCD_Binary ;将AX中的压缩型BCD码转换成二进制数
Exit_Proc: mov ah,4ch ;结束程序
int 21h
Code ENDS
END Start ;编译到此结束
2、在附加段中有一个数组,首地址为BUFF,数组中第一个字节存放了数组的长度编一个程序在数组中查找0,找到后把它从数组中删去,后续项向前压缩,其余部分补0。
; 本程序通过编译,运行正确
Code Segment
Assume CS:Code,DS:Code
BUFF db 10,56,78,35,0,89,51,63,0,76,123
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
cld
lea si,BUFF ;数组首地址→si
lodsb ;读数组长度
xor ah,ah
push ax
pop cx ;数组长度→cx
Find_Zero: lodsb ;数组元素读入累加器al
cmp al,0 ;是否为0
jnz Next_One ;不是0,跳转,处理下一个元素
; -----------------------------------------
; 找到0,把它从数组中删去,后续项向前压缩,其余部分补0。
push si
pop di
dec di
push di
push cx
dec cx
rep movsb
mov byte ptr [si-1],0
pop cx
pop si
; -----------------------------------------
Next_One: loop Find_Zero
Exit_Proc: mov ah,4ch ;结束程序
int 21h
Code ENDS
END Start ;编译到此结束
3编程序统计学生的数学成绩,分别归类90分~99分,80分~89分,70分~79分,60~69,及60分以下,并将各段的人数送入内存单元中。
; 本程序通过编译,运行正确
Code Segment
Assume CS:Code,DS:Code
; -----------------------------------------
; 功能:输出回车换行
enter_CTLF proc Near
push ax
push dx
mov ah,02h
mov dl,0dh
int 21h
mov dl,0ah
int 21h
pop dx
pop ax
ret
enter_CTLF endp
; -----------------------------------------
; 功能:把AL中的二进制无符号数转换成显式的十进制ASCII码
; 入口:AL=二进制数;di=转换后的ASCII保存地址
; 出口:无
Dec_ASCII Proc Near
push si
push cx
push bx
push di
mov bl,10
xor cx,cx
lea di,@@Temp_Save[3]
cld
@@Divide: xor ah,ah
div bl
or ah,30h
mov [di],ah
dec di
inc cx
test al,0ffh
jnz @@Divide
push di
pop si
inc si
pop di
pop bx
push di
rep movsb
mov byte ptr [di],'$'
pop di
pop cx
pop si
ret
@@Temp_Save db 4 dup()
Dec_ASCII EndP
; -----------------------------------------
Score db 56,69,84,82,73,88,99,63,100,80,0,10,80,100,90,73,43,60,63,72,88,42,58,99,100,89,65,61,74,84,79,2,60,61,62,62,66,82,79,71,62,63 ; 成绩单
Elements equ ($-Score)/Type Score ;元素个数
Score_Tab db 6 dup(0) ; 各分数段计数
Resault db '00---59: '
Temp_STr db 4 dup ('$')
Score100 db '====100: '
Start: push cs
pop ds
push cs
pop es ;使数据段、附加段与代码段同段
cld
lea si,Score ; 成绩首地址
mov cx,Elements ;成绩数目
mov dl,10 ; 用于除10
Read_Score: lodsb ; 提取成绩
div dl ; 除10
cmp al,5 ; >5,及格
jg $+4
mov al,5 ; <=5,不及格
sub al,5 ; 减5,分数段计数地址偏移量
cbw ;
push ax
pop bx
inc Score_Tab[bx] ; 计数增1
loop Read_Score ; 循环,统计下一个成绩
; 显示统计结果
mov bl,59h
mov cx,5
lea si,Score_Tab ;各分数段计数数组首地址
lea di,Temp_STr
lea dx,Resault ; 统计结果字符串地址
List_Resault:
lodsb ;读入计数值
call Dec_ASCII
mov ah,9 ; 显示统计结果
int 21h
call enter_CTLF
mov al,bl
add al,1
daa
mov bl,al
push cx
mov cl,4
xor ah,ah
shl ax,cl
shr al,cl
or ax,3030h
xchg ah,al
mov word ptr Resault,ax
mov al,bl
add al,9
mov bl,al
xor ah,ah
shl ax,cl
shr al,cl
or ax,3030h
xchg ah,al
mov word ptr Resault[5],ax
pop cx
loop List_Resault
push si
push di
lea si,Score100
lea di,Resault
lea cx,Temp_STr
sub cx,di
rep movsb
pop di
pop si
lodsb ;读入计数值
call Dec_ASCII
mov ah,9 ; 显示统计结果
int 21h
Exit_Proc: mov ah,4ch ;结束程序
int 21h
Code ENDS
END Start ;编译到此结束
8086是16位的,你问的应该是把BH(或者BL)的低八位和高八位分别送至DL和DH之中吧,下面我就举例把BH的高八位送至DH,低八位送至DL,(假如你想把BL拆分的话,只要把BH换为BL就可以了)只写主要部分给您,其他的不写
MOV AH,BH
AND BH,0F0H
MOV DH,BH
AND AH,0FH
MOV DL,BH
假如你真的想要将寄存器BX的高8值传送到寄存器DH,低8位传送到 寄存器DL
直接送就可以了
MOV DH,BH
MOV DL,BL
或者直接MOV DX,BX
1、程序如下:
code segment
assume cs:code, ds:code, ss:code
org 100h
main: mov si,offset x ;取数组中第一个元素的内存地址
mov cx,100 ;数组元素个数
cld ;以下使用lodsb来获得各元素值,为此先清除方向标志
xor ah,ah ;因x内全部为无符号数,所以将ah设为0,以便累加(根据 _fmlyht 意见从循环内移出以提高代码效率)
lab1: lodsb ;从ds:si处取一个字节放入al中,同时si增1即指向下个元素
add sum,ax ;累加
loop lab1 ;循环,前面对cx的赋值规定了循环次数为100次
int 20h ;循环结束后sum中为总和,此处用int 20h退出
x db 100 dup () ;定义100个字节型元素的数组,但不指定初值
sum dw 0 ;sum的初值为0,在程序代码部分中没有对该变量进行初始化,所以会使用这里定义的值为总和的初值
code ends
end main
2、代码如下:
cmp ax,bx ;比较ax与bx
jge lab2 ;若ax>=bx则转至lab2,带符号数比较须使用jg(e)/jl(e)/jng/jnl等指令
xchg ax,bx ;根据 _fmlyht 意见,将ax与bx交换,如此,ax中为两者的较大值,bx为较小值
lab2: cmp ax,cx ;执行到此时,ax中有最初时ax与bx中较大者,这时再比较ax与cx
jge lab3 ;方法与前次类似,至lab3时ax将存有原来三者中最大的数
xchg ax,cx ;没有跳转的话需将cx中较大的值与ax中较小的值交换以使ax中含最大值
lab3:
;至此ax中已是三者中的最大值,下面代码是为完成中间值与最小值的排序,使三者从大到小分别存放于ax、bx、cx。原题无此要求,可去掉。
cmp bx,cx
jge lab4
xchg bx,cx
lab4:
;至此,ax>=bx>=cx
----
谢谢楼下 _fmlyht 朋友指正,已在此答案中改进并注明。
为了简便,直接使用了21中断的输入字符串子功能,即使你不输入#作为结束符,也可以使用。
统计时,则将'#'后面的字符忽略
正确的作法,是调用21中断的1号子功能,每次读取一个字符,直到读取到'#'为止。
这个修改很简单,我就不再写了。
data segment
buf db 255 ;
db
db 255 dup('$')
c1 dw 0 ;spacebar
c2 dw 0 ;digital number
c3 dw 0 ;alphabet
m1 db 0dh, 0ah, "Spacebar number:$"
m2 db 0dh, 0ah, "Digital number:$"
m3 db 0dh, 0ah, "Alphabet number:$"
data ends
code segment
assume cs:code, ds:data
start:
mov ax, data
mov ds, ax
mov es, ax
;code start here
; read string
lea dx, buf
mov ah,0ah
int 21h
;
xor cx, cx
mov cl, buf+1
mov si, 0
Loop1:
mov al, buf[si+2]
cmp al, '#'
jz lopend
cmp al, 20h
jz space
cmp al, '0'
jb alphabet
cmp al, '9'
ja alphabet
inc c2 ;digital number
jmp lop
space:
inc c1 ;spacebar
jmp lop
alphabet:
inc c3
lop:
inc si
loop loop1
lopend:
; print result
lea dx, m1
mov ah, 9
int 21h
mov ax, c1
call print
lea dx, m2
mov ah, 9
int 21h
mov ax, c2
call print
lea dx, m3
mov ah,9
int 21h
mov ax, c3
call print
;exit to OS
mov ah,4ch
int 21h
print proc near
mov bx, 10
xor cx, cx
Q0:
xor dx, dx
div bx
or dx, 0e30h
push dx
inc cx
cmp ax, 0
jnz Q0
Q1:
pop ax
int 10h
loop Q1
ret
print endp
code ends
end start
以上就是关于求 十六位十进制求和 8086汇编 代码全部的内容,包括:求 十六位十进制求和 8086汇编 代码、8086的编程题(使用汇编语言)、编写8086汇编语言程序,将寄存器BX的高8值传送到寄存器DH,低8位传送到 寄存器DL。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)