上机5
商品数组products中按照商品ID(0-9之间)保存的每样商品对应的价格(假设价格为整数),从键盘输入需要购买的一组商品的ID(假设一次性购买商品不超过10件),计算需要购买商品的总价,并显示出来。假设商品的价格为55,10,25,13,90,5,15,24,68,20(id为0~9)
代码1
.model small
.386
.data
array dw 55, 10, 25, 13, 90, 5, 15, 24, 68, 20
N equ ($-array)/2
order db N dup(10)
cost dw ?
.stack
dw 10 dup(?)
.code
main proc far
mov ax, @data
mov ds, ax ;
call input
call calc
call crlf ; 输出回车
call output
mov ax, 4c00h
int 21h
main endp
;------------------------------------------
;------------------------------------------ 显示回车换行
crlf proc near
push dx ; 保护现场
mov dl, 0dh
mov ah, 2
int 21h
mov dl, 0ah
mov ah, 2
int 21h
pop dx
ret
crlf endp
;------------------------------------------ 输入
input proc near
push ax ; 保护现场
push cx
push si
mov ax, 0
mov si, 0
mov cx, N
readloop:
; 读取
mov ah, 1
int 21h
; 如果是回车,跳出
cmp al, 0dh
je endread
; 保存
sub al, 30h ; ascii 转 数字
mov order[si], al
inc si
loop readloop
endread:
pop si
pop cx
pop ax
ret
input endp
;------------------------------------------ 输出(16进制转10进制,并输出)(除10取余法)
output proc near
push ax
push bx
push cx
push dx
mov cx, 1
mov bx, 10
mov ax, cost
realin:
div bx ; 存余数
push dx ; 余数进栈
cmp ax, 0 ; 是否已除净
jle realout
mov dx, 0
inc cx
jmp realin
realout:
pop dx
add dx, 30h
mov ah, 2 ; 输出
int 21h
loop realout
pop dx
pop cx
pop bx
pop ax
ret
output endp
;------------------------------------------ 计算
calc proc near
push ax ; 保存结果
push bx ; 临时存储 array 数组需要的元素
push cx ; 循环计数器
push dx ; 临时存储 order 数组需要的元素
push si ; order 下标
mov ax, 0
mov bx, 0
mov cx, N
mov dx, 0
mov si, 0
calcloop:
mov dl, order[si]
; 如果是 10(表示超出商品最大下标),跳出
cmp dl, 10
je endcalc
push si ; 保护 order 的下标
mov si, dx
add si, si ; 操作16位数,两倍si
; 计算
mov bx, array[si]
add ax, bx
pop si ; 取出 order 的下标
inc si
loop calcloop
endcalc:
; 结束计算
mov cost, ax
pop si
pop dx
pop cx
pop bx
pop ax
ret
calc endp
end main
代码2
ASSUME cs:code,ds:data
data SEGMENT
commodity db 55,10,25,13,90,5,15,24,68,20
id db 10 dup(0)
ENDS
code SEGMENT
start:
mov ax,data
mov ds,ax
;=========子函数执行==========
call input;输入
call calculate;计算
call output;输出
mov ah,4CH
int 21H
input proc
mov cx,10
mov si,0
s:
MOV ah,01H ;调用1号功能输入字符(只能输入一个字符)
INT 21H
cmp al,0dh
je end_input;输入回车则结束输出
sub al,48;al为 id
mov ah,0
mov di,ax
inc id[di];给对应的id 加1
;例如 10件 id 为1的商品,id数组则为 10,0,0,0,0,0,0,0,0,0
loop s
;输入10个则输出换行
mov ah,02H
mov dl,0AH
int 21H
end_input:
ret
input endp
;计算结果存放在bx中,
calculate proc
mov cx,10
mov si,0
mov ax,0
mov bx,0
s1:
;al 商品价值
;dl 商品数量
mov al,commodity[si]
mov dl,id[si]
mul dl
;dx中存放高位
add bx,ax
inc si
loop s1
ret
calculate endp
;入口为bx
output proc
mov ax,bx;the number that needed to be output is saved in bx , now move it to ax
mov bx,10
mov cx,0;cx记录需要输出多少个个数
division:
mov dx,0;dx每次除完必须置为0,否则回引起溢出问题
div bx
push dx; save the remainder in stack
inc cx
cmp ax,0
jne division ;if the ax is not zero,means still need ax still need to be divided
;!!! 必须先把栈清空在ret,使得ss:sp回到正常位置。否则ret无法正常工作
;提问网址 https://stackoverflow.com/questions/67950097/in-my-assembly-code-the-subroutine-returned-but-the-code-started-again-from-b
print:
pop dx
add dl,48
mov ah,02H
int 21H
loop print
ret
output endp
ENDS
END start
上机6
从键盘输入n,计算其对应的斐波那契函数的fib(n),并输出结果。
代码1
.model small
.386
.data
buf db 20h
db 0
db 20h dup(?) ; 缓冲区存储字符串
result dd ? ; 32767 为dw最大表示数
n dd ? ; 字符串转换成数字后的临时存储单元
.stack
dw 100 dup(?)
.code
main proc far
mov ax, @data
mov ds, ax ;
call input
call crlf ; 输出回车
call trans
mov eax, n ; eax 传参
call fibo
mov result, eax
call output
mov ax, 4c00h
int 21h
main endp
;------------------------------------------
;------------------------------------------ 显示回车换行子程序
crlf proc near
push dx ; 保护现场
mov dl, 0dh
mov ah, 2
int 21h
mov dl, 0ah
mov ah, 2
int 21h
pop dx
ret
crlf endp
;------------------------------------------ 输入
input proc near
push ax
push dx ; 保护现场
readloop:
mov ah, 0ah
lea dx, buf
int 21h
endread:
pop dx
pop ax
ret
input endp
;------------------------------------------ 输出(16进制转10进制,并输出)(除10取余法)
output proc near
push eax
push ebx
push ecx
push edx
mov ecx, 1
mov ebx, 10
mov eax, result
realin:
div ebx ; 存余数
push edx ; 余数进栈
cmp eax, 0 ; 是否已除净
jle realout
mov edx, 0
inc ecx
jmp realin
realout:
pop edx
add edx, 30h
mov ah, 2 ; 输出
int 21h
loop realout
pop edx
pop ecx
pop ebx
pop eax
ret
output endp
;------------------------------------------ 计算
fibo proc near
push ebx
push ecx
push edx
cmp eax, 1
je endfibo
cmp eax, 2
je endfibo ; n == 1 或 n == 2 返回 1
mov edx, eax
sub eax, 1
call fibo
mov ebx, eax
mov eax, edx
sub eax, 2
call fibo
mov ecx, eax
mov eax, ebx
add eax, ecx
pop edx
pop ecx
pop ebx
ret
endfibo:
mov eax, 1
pop edx
pop ecx
pop ebx
ret
fibo endp
;------------------------------------------ 字符串转数字预处理
trans proc near
push ax
push bx
push cx
push dx
push si
mov dx, 0
mov bx, 10
mov si, 2
mov ax, 0
maintrans:
mov al, buf[si]
cmp al, 0dh
je endtrans
sub al, 30h
cmp n, 0
je realtrans
push eax
mov eax, n
mul ebx
mov n, eax
pop eax
realtrans:
add n, eax
mov eax, 0
inc si
jmp maintrans
endtrans:
pop si
pop dx
pop cx
pop bx
pop ax
ret
trans endp
end main
代码2
ASSUME cs:code,ds:data
data SEGMENT
str db 10 dup(0)
save_al db 0
ten db 10
temp dw 0
ENDS
code SEGMENT
start:
mov ax,data
mov ds,ax
;=========子函数执行==========
call input
call fib
call output
mov ah,4CH
int 21H
;输入
input proc
mov si,0
s:
MOV ah,01H ;调用1号功能输入字符(只能输入一个字符)
INT 21H
cmp al,0dh
je end_input ;输入回车则结束输出
sub al,48;al为输入的字符
mov str[si],al
inc si
jmp s ;不是回车则继续输入
end_input:
;结果存在bx中
call string_to_integer
ret
input endp
; 把输入的string 转int
string_to_integer proc
mov cx,si
mov al,1;从最后一位往前计算
sub si,1
mov bx,0
s2:
mov save_al,al
mul str[si];执行完成后ax中存着这意味对应的十位数
sub si,1
add bx,ax
mov al,save_al
mul ten;al = al*10
loop s2
ret
string_to_integer endp
;计算斐波那契
fib proc
; 伪代码
; #bx中为结果
; ax=0
; bx=1
; if cx==0:
; bx=0
; else if cx==1:
; bx=1
; else
; for i in range(cx):
; ax= ax + bx
; temp=ax
; ax=bx
; bx=tem
mov cx,bx
mov ax,0
mov bx,1
cmp cx,0
je cx_equal_0
cmp cx,1
je cx_equal_1
;当 cx>1 时执行以下程序
sub cx,1;cx 先减一
s5:
add ax,bx
mov temp,ax
mov ax,bx
mov bx,temp
loop s5
ret
cx_equal_0:
mov bx,0
ret
cx_equal_1:
mov bx,1
ret
fib endp
;入口为bx
output proc
mov ax,bx;the number that needed to be output is saved in bx , now move it to ax
mov bx,10
mov cx,0;cx记录需要输出多少个个数
division:
mov dx,0;dx每次除完必须置为0,否则回引起溢出问题
div bx
push dx; save the remainder in stack
inc cx
cmp ax,0
jne division ;if the ax is not zero,means still need ax still need to be divided
;!!! 必须先把栈清空在ret,使得ss:sp回到正常位置。否则ret无法正常工作
;提问网址 https://stackoverflow.com/questions/67950097/in-my-assembly-code-the-subroutine-returned-but-the-code-started-again-from-b
print:
pop dx
add dl,48
mov ah,02H
int 21H
loop print
ret
output endp
ENDS
END start