
name "calc2"
; command prompt based simple calculator (+,-,,/) for 8086
; example of calculation:
; input 1 <- number: 10
; input 2 <- operator: -
; input 3 <- number: 5
; -------------------
; 10 - 5 = 5
; output -> number: 5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; this maro is copied from emu8086inc ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; this macro prints a char in AL and advances
; the current cursor position:
PUTC MACRO char
PUSH AX
MOV AL, char
MOV AH, 0Eh
INT 10h
POP AX
ENDM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 100h
jmp start
; define variables:
msg0 db "note: calculator works with integer values only",0Dh,0Ah
db "to learn how to output the result of a float division see floatasm in examples",0Dh,0Ah,'$'
msg1 db 0Dh,0Ah, 0Dh,0Ah, 'enter first number: $'
msg2 db "enter the operator: + - / : $"
msg3 db "enter second number: $"
msg4 db 0dh,0ah , 'the approximate result of my calculations is : $'
msg5 db 0dh,0ah ,'thank you for using the calculator! press any key ', 0Dh,0Ah, '$'
err1 db "wrong operator!", 0Dh,0Ah , '$'
smth db " and something $"
; operator can be: '+','-','','/' or 'q' to exit in the middle
opr db ''
; first and second number:
num1 dw
num2 dw
start:
mov dx, offset msg0
mov ah, 9
int 21h
lea dx, msg1
mov ah, 09h ; output string at ds:dx
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store first number:
mov num1, cx
; new line:
putc 0Dh
putc 0Ah
lea dx, msg2
mov ah, 09h ; output string at ds:dx
int 21h
; get operator:
mov ah, 1 ; single char input to AL
int 21h
mov opr, al
; new line:
putc 0Dh
putc 0Ah
cmp opr, 'q' ; q - exit in the middle
je exit
cmp opr, ''
jb wrong_opr
cmp opr, '/'
ja wrong_opr
; output of a string at ds:dx
lea dx, msg3
mov ah, 09h
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store second number:
mov num2, cx
lea dx, msg4
mov ah, 09h ; output string at ds:dx
int 21h
; calculate:
cmp opr, '+'
je do_plus
cmp opr, '-'
je do_minus
cmp opr, ''
je do_mult
cmp opr, '/'
je do_div
; none of the above
wrong_opr:
lea dx, err1
mov ah, 09h ; output string at ds:dx
int 21h
exit:
; output of a string at ds:dx
lea dx, msg5
mov ah, 09h
int 21h
; wait for any key
mov ah, 0
int 16h
ret ; return back to os
do_plus:
mov ax, num1
add ax, num2
call print_num ; print ax value
jmp exit
do_minus:
mov ax, num1
sub ax, num2
call print_num ; print ax value
jmp exit
do_mult:
mov ax, num1
imul num2 ; (dx ax) = ax num2
call print_num ; print ax value
; dx is ignored (calc works with tiny numbers only)
jmp exit
do_div:
; dx is ignored (calc works with tiny integer numbers only)
mov dx, 0
mov ax, num1
idiv num2 ; ax = (dx ax) / num2
cmp dx, 0
jnz approx
call print_num ; print ax value
jmp exit
approx:
call print_num ; print ax value
lea dx, smth
mov ah, 09h ; output string at ds:dx
int 21h
jmp exit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; these functions are copied from emu8086inc ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; gets the multi-digit SIGNED number from the keyboard,
; and stores the result in CX register:
SCAN_NUM PROC NEAR
PUSH DX
PUSH AX
PUSH SI
MOV CX, 0
; reset flag:
MOV CS:make_minus, 0
next_digit:
; get char from keyboard
; into AL:
MOV AH, 00h
INT 16h
; and print it:
MOV AH, 0Eh
INT 10h
; check for MINUS:
CMP AL, '-'
JE set_minus
; check for ENTER key:
CMP AL, 0Dh ; carriage return
JNE not_cr
JMP stop_input
not_cr:
CMP AL, 8 ; 'BACKSPACE' pressed
JNE backspace_checked
MOV DX, 0 ; remove last digit by
MOV AX, CX ; division:
DIV CS:ten ; AX = DX:AX / 10 (DX-rem)
MOV CX, AX
PUTC ' ' ; clear position
PUTC 8 ; backspace again
JMP next_digit
backspace_checked:
; allow only digits:
CMP AL, '0'
JAE ok_AE_0
JMP remove_not_digit
ok_AE_0:
CMP AL, '9'
JBE ok_digit
remove_not_digit:
PUTC 8 ; backspace
PUTC ' ' ; clear last entered not digit
PUTC 8 ; backspace again
JMP next_digit ; wait for next input
ok_digit:
; multiply CX by 10 (first time the result is zero)
PUSH AX
MOV AX, CX
MUL CS:ten ; DX:AX = AX10
MOV CX, AX
POP AX
; check if the number is too big
; (result should be 16 bits)
CMP DX, 0
JNE too_big
; convert from ASCII code:
SUB AL, 30h
; add AL to CX:
MOV AH, 0
MOV DX, CX ; backup, in case the result will be too big
ADD CX, AX
JC too_big2 ; jump if the number is too big
JMP next_digit
set_minus:
MOV CS:make_minus, 1
JMP next_digit
too_big2:
MOV CX, DX ; restore the backuped value before add
MOV DX, 0 ; DX was zero before backup!
too_big:
MOV AX, CX
DIV CS:ten ; reverse last DX:AX = AX10, make AX = DX:AX / 10
MOV CX, AX
PUTC 8 ; backspace
PUTC ' ' ; clear last entered digit
PUTC 8 ; backspace again
JMP next_digit ; wait for Enter/Backspace
stop_input:
; check flag:
CMP CS:make_minus, 0
JE not_minus
NEG CX
not_minus:
POP SI
POP AX
POP DX
RET
make_minus DB ; used as a flag
SCAN_NUM ENDP
; this procedure prints number in AX,
; used with PRINT_NUM_UNS to print signed numbers:
PRINT_NUM PROC NEAR
PUSH DX
PUSH AX
CMP AX, 0
JNZ not_zero
PUTC '0'
JMP printed
not_zero:
; the check SIGN of AX,
; make absolute if it's negative:
CMP AX, 0
JNS positive
NEG AX
PUTC '-'
positive:
CALL PRINT_NUM_UNS
printed:
POP AX
POP DX
RET
PRINT_NUM ENDP
; this procedure prints out an unsigned
; number in AX (not just a single digit)
; allowed values are from 0 to 65535 (FFFF)
PRINT_NUM_UNS PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSH DX
; flag to prevent printing zeros before number:
MOV CX, 1
; (result of "/ 10000" is always less or equal to 9)
MOV BX, 10000 ; 2710h - divider
; AX is zero
CMP AX, 0
JZ print_zero
begin_print:
; check divider (if zero go to end_print):
CMP BX,0
JZ end_print
; avoid printing zeros before number:
CMP CX, 0
JE calc
; if AX<BX then result of DIV will be zero:
CMP AX, BX
JB skip
calc:
MOV CX, 0 ; set flag
MOV DX, 0
DIV BX ; AX = DX:AX / BX (DX=remainder)
; print last digit
; AH is always ZERO, so it's ignored
ADD AL, 30h ; convert to ASCII code
PUTC AL
MOV AX, DX ; get remainder from last div
skip:
; calculate BX=BX/10
PUSH AX
MOV DX, 0
MOV AX, BX
DIV CS:ten ; AX = DX:AX / 10 (DX=remainder)
MOV BX, AX
POP AX
JMP begin_print
print_zero:
PUTC '0'
end_print:
POP DX
POP CX
POP BX
POP AX
RET
PRINT_NUM_UNS ENDP
ten DW 10 ; used as multiplier/divider by SCAN_NUM & PRINT_NUM_UNS
GET_STRING PROC NEAR
PUSH AX
PUSH CX
PUSH DI
PUSH DX
MOV CX, 0 ; char counter
CMP DX, 1 ; buffer too small
JBE empty_buffer ;
DEC DX ; reserve space for last zero
;============================
; Eternal loop to get
; and processes key presses:
wait_for_key:
MOV AH, 0 ; get pressed key
INT 16h
CMP AL, 0Dh ; 'RETURN' pressed
JZ exit_GET_STRING
CMP AL, 8 ; 'BACKSPACE' pressed
JNE add_to_buffer
JCXZ wait_for_key ; nothing to remove!
DEC CX
DEC DI
PUTC 8 ; backspace
PUTC ' ' ; clear position
PUTC 8 ; backspace again
JMP wait_for_key
add_to_buffer:
CMP CX, DX ; buffer is full
JAE wait_for_key ; if so wait for 'BACKSPACE' or 'RETURN'
MOV [DI], AL
INC DI
INC CX
; print the key:
MOV AH, 0Eh
INT 10h
JMP wait_for_key
;============================
exit_GET_STRING:
; terminate by null:
MOV [DI], 0
empty_buffer:
POP DX
POP DI
POP CX
POP AX
RET
GET_STRING ENDP
分类: 电脑/网络 >> 程序设计 >> 其他编程语言
问题描述:
31. MOV DL,AL
NOT DL
TEST DL,04H
JE NEXT
┇
NEXT:…
若上述程序段执行时产生分支,说明AL中的数第几位一定为1?程序段执行后CF是多少?
32.DA1 DB‘ABCDEFGHI’
DA2 DB 9 DUP(0)
┇
LEA SI,DA1
LEA DI,DA2
MOV CX,9
CLD
LOP: LODSB
SUB AL,10H
STOSB
LOOP LOP
试问:①写出程序执行后DA2各字节中的数据。
②保持程序功能情况下,程序中 可否改写为
33.已知:BX=4567H
NEG BX
INC BX
NEG BX
DEC BX
程序段执行后,BX=________,CF=________。
34. MOV BL,64H
MOV CL,03H
XOR AX,AX
AGAIN:ADD AL,BL
ADC AH,0
DEC CL
JNZ AGAIN
问:(1)该程序段完成的功能是:
(2)AX=________。
35.已知数据段中定义
DAT1 DB 12H,34H,56H,78H
MOV CX,0
MOV AX,WORD PTR DAT1
MOV CL,DAT1+3
当程序段执行完后AX=________,CX=________。
36.DA1 DB 83H,72H,61H,94H,5AH
┇
MOV CX,WORD PTR DA1
AND CX,0FH
MOV AL,DA1+3
SHL AL,CL
上述指令序列执行后,AL=_______,CL=_______。
解析:
31.从第0位开始数的第2位一定为1;CF=0
32.
①""
②保持程序功能情况下,程序中 可否改写为 ——什么呀,题目都不完整
33.BX=4564H,CF=1
34.
(1)100+100+100
(2)AX=012CH
35.AX=3412H,CX=0078H
36.AL=0A0H,CL=3
汇编语言程序设计的基本步骤 了解了汇编语言指令的功能和用法,了解了汇编语言程序的编写格式,就可以编制完整的汇编语言程序了。一个程序通常具有顺序、分支、循环和子程序4种结构形式。顺序程序结构就是指完全按顺序逐条执行的指令序列。在程序设计过程中,顺序结构大量存在,屡见不鲜。但一个完整的程序只是逐条去执行指令,这非常少见。常见的程序结构,是上述4种结构的混合体。一般来说,编制一个汇编语言程序的步骤如下:(1) 分析题意,确定算法或算法思想。算法是指解决问题的方法和步骤。比如现有的一些计算方法和日常生活中解决问题的逻辑思维推理方法等。(2) 根据算法画出流程图,简单的情况也可不画。画出描述算法的流程图,可以首先从图上检验算法的正确性,减少出错的可能,使得动手编写程序时的思路更加清晰。(3) 分配存储空间和工作单元,合理地使用寄存器。分配存储空间和工作单元,是指存储空间的分段和数据定义。另外,由于寄存器的数量有限,编写程序时经常会感到寄存器不够用。因此,对于字节数据,要尽量使用8位寄存器。而采用适当的寻址方式,也会达到节省寄存器的目的。(4) 根据流程图编写程序。这是编制汇编语言程序最为重要的一步。算法里规定的功能,是要通过一条条指令描述出来的。为了提高编程能力,对于初学者,一是要多阅读现有的程序,以学习别人的编程经验;而更为重要的是,必须多亲自动手编写,不要怕失败,只有通过无数次失败,才能从中积累自己的编程经验。(5) 上机调试运行程序。通过汇编的源程序,只能说明它里面不存在语法错误。但是它是否能达到算法所要求的预期效果,还必须经过上机调试,用一些实验数据来测试,才能够真正地得出结论。可以这么说,即使是一个非常有经验的程序员,也没有百分之百的把握说他编写的程序一次就成功。 用流程图表示算法 流程图用一些图形框来代表各种 *** 作。用图形表示算法,直观形象,可以用来帮助人们对算法的理解。下图给出了一些常用的流程图符号。
上图中的判断框(菱形)用来对一个给定的条件作出判断,以决定如何执行其后的 *** 作。它有一个入口,两个出口,如下图(a)所示。
连接点(圆圈)是用来将画在不同地方的流程线连接起来。例如在下图(b)里,有两个圈里写着数字1的圆圈,它表示是从左边的1出来,进到右边图的1里(这由流程线的方向给出)。可以看出,这两个点其实就是同一个点,只是由于画不下而分开来画的。用连接点,可以避免流程图中的流程线相互交叉或过长,从而使流程图清晰。
注释框不是流程图中必需的部分。在流程图中使用它,是为了对流程图中的某些框的 *** 作做一些必要的说明,以便使人们能够更好地通过流程图来理解算法。
处理框反映做些什么样的 *** 作,如把某个单元的内容送入某个寄存器,从某个存储单元取出数据等。它是流程图里最为本质的、出现最多的图形框。
输入/输出框反映程序的输入和输出情况。计算机程序无外乎接收数据,进行处理,然后加以输出,所以输入/输出框是必不可少的。
编码不容易,望能帮到楼主。楼主好好看
CRLFMACRO;宏定义,实现回车换行
MOVAH,2
MOVDL,0DH
INT21H
MOVAH,2
MOVDL,0AH
INT21H
ENDM
DSEGMENT
SCOREDB76,69,84,90,73,88,89,63,100,80;数组接收分数
SDB5DUP();预留5个位置存储每个分数段的人数
WORDSDB"THENUMBERBETWEEN60~69IS:$"
WORDS1DB"THENUMBERBETWEEN70~79IS:$"
WORDS2DB"THENUMBERBETWEEN80~89IS:$"
WORDS3DB"THENUMBERBETWEEN90~99IS:$"
WORDS4DB"THENUMBERBETWEEN100IS:$"
DENDS
CODESEGMENT
ASSUMECS:CODE,DS:D
BG:
MOVAX,D
MOVDS,AX
CALLCOUNT;调用子程序
MOVAH,9;输出每个分数段的人数
LEADX,WORDS
INT21H
MOVAH,2
MOVDL,S
ADDDL,30H
INT21H
CRLF
MOVAH,9
LEADX,WORDS1
INT21H
MOVAH,2
MOVDL,S1
ADDDL,30H
INT21H
CRLF
MOVAH,9
LEADX,WORDS2
INT21H
MOVAH,2
MOVDL,S2
ADDDL,30H
INT21H
CRLF
MOVAH,9
LEADX,WORDS3
INT21H
MOVAH,2
MOVDL,S3
ADDDL,30H
INT21H
CRLF
MOVAH,9
LEADX,WORDS4
INT21H
MOVAH,2
MOVDL,S4
ADDDL,30H
INT21H
CRLF
MOVAH,4CH
INT21H
COUNT:;子程序入口
MOVCX,10;循环10次
MOVSI,0
LOP:
INT3
MOVAL,SCORE[SI]
CMPAL,70
JBNUMBER6;比较进入不同的标号进行计算每个分数段人数
CMPAL,80
JBNUMBER7
CMPAL,90
JBNUMBER8
CMPAL,100
JENUMBER10
JMPNUMBER9
NUMBER6:;不同标号之下的作用是计算每个分数段人数并存于预留的位置中
MOVBL,S
INCBL
MOVS,BL
JMPL
NUMBER7:
MOVBL,S1
INCBL
MOVS1,BL
JMPL
NUMBER8:
MOVBL,S2
INCBL
MOVS2,BL
JMPL
NUMBER9:
MOVBL,S3
INCBL
MOVS3,BL
JMPL
NUMBER10:
MOVBL,S4
INCBL
MOVS4,BL
JMPL
L:
INCSI
LOOPLOP
RET;子程序结束,放回主程序
CODEENDS
ENDBG
汇编语言程序设计步骤:1、 分析问题,抽象出描述问题的数据模型 2、 确定问题的算法思想 3、 画出流程图或结构图 4、 分配存储器和工作单元(寄存器) 5、 逐条编写程序 6、 静态检查,上机调试 例:编程查找考生的最高分,假设所有考生分数已存入计算机内存1、 分析问题 根据条件、特点、规律 →数学模型 本例分数已给定为0~200之间的整数集合(考虑加试分) ,记为{S},找max{S}(注:简单问题不一定写数学模型) 2、 确定算法思想 最好利用现成算法和程序设计方法,若无,则需根据实践经验总结算法思想如本例,从成绩单第一分数往下看,边看边比较,记住较高分,舍弃较低分,直至看完,最高分存于 脑中归纳算法思想:建立数据指针并指向数据区首地址将第一数取入寄存器(如AL) ,与下一数比较,若下一数大则将其取入寄存器,否则调整指针,再与下一数比较,重复上述 直至比较完毕,寄存器中即最高分读分数用MOV指令,比较用CMP指令,分析判断用条件转移指令3、 画流程图或结构图 有逻辑流程、算法流程、程序流程等,复杂问题需画模块结构本例简单,只画出程序 流程图(用模块化结构的N-S流程图表示) :本例的N-S流程图 图中初始化包括:设一个计数器,将分数个数减一后送计数器,每比较一次减一,至 零查找结束;建立一个指针指向数据区开始 初始化 取第一数到寄存器 与下一数比较 下一数大是 否 取大数到寄存器 修改指针,计数次数减一 返回到循环体开始,直到计数次数为0退出循环 结束 4、 分配存储器空间和工作单元(寄存器) 定义数据段、堆栈段、代码段等工作单元一般用寄存器本例:分数放数据段,建100 字节堆栈空间,BX作数据指针,CX作计数器,AL放最高分5、 逐条编写程序 DATA SEGMENT FEN DB 85,90,60,75,87,35,80,78,96,82…… ;存分数 MAX DB ;存最高分 DATA ENDS STACK SEGMENT PARA STACK ‘STACK’ DB 100 DUP() ;100字节堆栈 STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK START PROC FAR PUSH DS MOV AX,0 PUSH AX ;为了返回DOS MOV AX,DATA MOV DS,AX ;置数据段寄存器 MOV BX,OFFSET FEN ;置数据指针 MOV CX,MAX-FEN ;置计数器初值 DEC CX ;N个分数比较N-1次 MOV AL,[BX] ;取第一个分数 LOP:INC BX ;调整指针 CMP AL,[BX] ;与下一数比较 JAE NEXT ;大于等于则转 MOV AL,[BX] ;否则取下一数 NEXT:LOOP LOP ;计数器减一,;不为零转LOP MOV MAX,AL ;存放最高分 RET ;返回DOS START ENDP CODE ENDS END START 6、 静态检查,上机调试 选用指令尽量字节少,使其执行速度快易错处应重点查,如比较次数、转移条件等确信无错后方可上机调试
以上就是关于汇编语言程序设计全部的内容,包括:汇编语言程序设计、高手请进,问汇编语言程序设计问题、汇编语言程序设计的一般步骤是什么等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)