Logo

加载中

汇编代码

1.1 将 ('47''69') 进行相加(即 47+69),计算并显示其十进制结果('116')。

字符 '0' = 48D = 30H
字符 '1' = 49D = 31H  
字符 '2' = 50D = 32H
字符 '3' = 51D = 33H
字符 '4' = 52D = 34H
字符 '5' = 53D = 35H
字符 '6' = 54D = 36H
字符 '7' = 55D = 37H
字符 '8' = 56D = 38H
字符 '9' = 57D = 39H

题外话1:AAD —— ASCII Adjust for Division
MOV AH, '4'      ; AH = 34H
MOV AL, '7'      ; AL = 37H
SUB AX, 3030H    ; AH = 04H, AL = 07H
AAD              ; AX = 04*10 + 07 = 47 (002FH)
                 ; 现在AX中是真正的二进制数47,可以直接进行数学运算
题外话2:AAA —— ASCII Adjust After Addition
电脑是怎么"笨笨地"算的:
电脑算 7 + 9:
电脑里:7 = 00000111,9 = 00001001
直接加:00000111 + 00001001 = 00010000(这是16,写成十六进制是10H)
问题来了:
电脑得到的 10H(十六进制的16)中:
1 在"十六进制的十位"(实际是16的1)
0 在个位
但我们要的是十进制的16,应该是:
十位 = 1
个位 = 6
AAA来救场了!
AAA看到 10H,心想:"哦!这看起来像是有进位的情况(因为低4位加出了16)。"于是它做两件事:
给个位加6:10H + 6 = 16H,然后只留下个位6
给十位加1:把进位1存到AH寄存器里
结果:
AL(个位寄存器) = 6
AH(十位/进位寄存器) = 原来的AH + 1
DATA    SEGMENT    
VAL1    BYTE '47'
VAL2    BYTE '69'
RES     BYTE 4 DUP (?)
DATA    ENDS

STACK   SEGMENT STACK 'STACK'    
BYTE    100 DUP (?)
STACK   ENDS

CODE    SEGMENT            
ASSUME CS:CODE, DS:DATA, SS:STACK

START:
    MOV AX, DATA        
    MOV DS, AX          

    ; 计算个位 7+9
    MOV AL, VAL1+1
    SUB AL, '0'
    MOV BL, VAL2+1
    SUB BL, '0'
    ADD AL, BL
    AAA
    MOV RES+2, AL
    
    ; 计算十位 4+6+进位
    MOV AL, VAL1
    SUB AL, '0'
    MOV BL, VAL2
    SUB BL, '0'
    ADD AL, BL
    ADD AL, AH
    MOV AH, 0
    AAA
    MOV RES+1, AL
    
    ; 处理百位
    ADD AH, '0'
    MOV RES, AH
    
    ; 转换为ASCII
    ADD RES+2, '0'
    ADD RES+1, '0'

    MOV RES+3, '$'
    
    MOV DX, OFFSET RES
    MOV AH, 9    
    INT 21H
    
    MOV AH, 4CH    
    INT 21H        
CODE    ENDS
END START

2.1 查表转换。使用 XLAT 指令,将一个BCD码数字 (05H) 通过七段数码管码表,转换为对应的段码,并存储结果。

.MODEL	SMALL
.STACK  	64
.DATA
TABLE7	BYTE  3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
VALBCD	BYTE 05H
RES7	BYTE  ?	
.CODE
.STARTUP	
MOV BX, OFFSET TABLE7
MOV AL, VALBCD
XLAT            
MOV RES7, AL
.EXIT		
END 

3.1 显示一条信息,等待用户输入。如果用户输入 'Y',则显示一条特定信息;否则显示另一条。

DISP	MACRO	STR
MOV DX, OFFSET STR
MOV AH, 9
INT 21H
ENDM
.MODEL	SMALL
.STACK	64
.DATA
PROMPT1  BYTE 'There is a message for you from NEO.', SPACE
BYTE 'To read it enter Y','$'
MESSAGE   BYTE CR, LF, 'HI! I will meet you in the Matrix in 3009.', '$'
PROMPT2  BYTE	CR, LF, 'No more messages for you.', '$'
CR 	EQU	0DH	
LF	EQU	0AH
SPACE	EQU	20H
.CODE
START:	MOV AX,@DATA
MOV DS,AX
DISP PROMPT1
MOV AH, 7
INT 21H
CMP AL, 'Y'
JZ OVER
DISP PROMPT2
JMP EXIT
OVER:	DISP MESSAGE
EXIT:	MOV AH,4CH
INT 21H
END START

4.1 计算 {10*(X+Y) - 3*(Z-1)} / 2

TITLE    EXAMPLE  PROGRAM
DATA  SEGMENT	;设置数据段
VARX	DW    123H	;变量X
VARY	DW    456H	;变量Y
VARZ	DW    789H	;变量Z
FUN		DW    ?	;结果单元
DATA   	ENDS
STACK1  	SEGMENT   PARA  STACK;设置堆栈段
DW   20H   DUP(0)
STACK1  	ENDS
CODE	SEGMENT		;设置代码段
ASSUME   CS: CODE, DS: DATA, SS: STACK1
START:	MOV	  AX, DATA	;置段基值于DS
MOV	  DS, AX
MOV	  AX, VARX	;取变量X
ADD	  AX, VARY	;AX =(X+Y)
MOV	  BX, AX	;BX =(X+Y)
SAL	  AX, 1		;AX=2*(X+Y)
SAL	  AX, 1		;AX = 4*(X+Y)
ADD	  AX, BX	;AX = 5*(X+Y)
SAL	  AX, 1		;AX = 10*(X+Y)
MOV	  BX, VARZ	;取变量Z
DEC	  BX		;BX =(Z-1)
MOV	  CX, BX	;CX =(Z-1)
SAL	  BX, 1		;BX = 2*(Z-1)
ADD	  BX, CX	;BX = 3*(Z-1)
SUB	  AX, BX	;AX = 10*(X+Y)- 3*(Z-1)
SAR	  AX, 1		;AX = {10*(X+Y)- 3*(Z-1)}/2
MOV	  FUN,AX	;存放计算结果
MOV	  AH,4CH	;终止用户程序,返回DOS
INT	  21H
CODE	ENDS
END  START

5.1 基于固定值的跳转表法的(A+, A, A-, B+, B)。

.MODEL SMALL
.DATA
SCORE BYTE 60
AP BYTE 'A+','$'
A BYTE 'A','$'
AM BYTE 'A-','$'
BPL BYTE 'B+','$'
B BYTE 'B','$'
J_TAB WORD L1 ,L2,L3,L4,L5
.CODE
START: MOV AX, @DATA ;初始化段寄存器
MOV DS, AX
XOR AH,AH
MOV AL,SCORE ;
SUB AL,60   ; AL=AL-60
MOV BL,10   ; BL =10
DIV BL      ; 将分数段划分为 10 分一个区间 AL/10,商存入AL,余数存入AH
MOV BL,AL   ; 将商从AL传到BL
XOR BH,BH   ; 实现多分支的程序段, 使得BX寄存器的高8位为0
SHL BX,1    ; 计算2*(PARAM)
JMP J_TAB[BX]; 根据索引跳转到跳转表
L1: MOV DX,OFFSET B
MOV AH,9  ; 显示
INT 21H
JMP NEXT
L2: MOV DX,OFFSET BPL
MOV AH,9
INT 21H
JMP NEXT
L3: MOV DX,OFFSET AM
MOV AH,9
INT 21H
JMP NEXT
L4: MOV DX,OFFSET A
MOV AH,9
INT 21H
JMP NEXT
L5: MOV DX,OFFSET AP
MOV AH,9
INT 21H
JMP NEXT
NEXT: MOV AH, 4CH
INT 21H
END START

5.2 带输入的跳转表法。

DATA SEGMENT
buf   db 3        ;缓冲区长度
db ?        ;实际输入个数
str1  db 3 DUP(?) ;存储空间

score db 87
disp   db 0dh, 0ah
grade db ?,'$'

; 跳转表:存储各个分支的地址
jmp_table dw branch1, branch2, branch3, branch4
DATA ENDS

STACK1 SEGMENT PARA STACK
DW 40H DUP(?)
STACK1 ENDS

CODE SEGMENT
ASSUME CS:CODE , DS:DATA
START: MOV AX,DATA
MOV DS,AX
mov dx, offset buf
mov ah, 0ah
int 21h

;=(str1[0]-'0')*10+(str1[1]-'0')=
mov al, str1[0]
sub al,'0'
mov bl, 10
mul bl
mov bl, str1[1]
sub bl, '0'
add al, bl

; 将成绩存入score变量
mov score, al

; 使用跳转表法判断等级
mov al, score
cmp al, 90
jae level0      ; >=90 跳转到level0
cmp al, 80
jae level1      ; >=80 跳转到level1
cmp al, 70
jae level2      ; >=70 跳转到level2
jmp level3      ; 其他情况跳转到level3
level0:
mov bx, 0       ; 对应branch1在跳转表中的索引0
jmp do_jump
level1:
mov bx, 2       ; 对应branch2在跳转表中的索引1(每个地址占2字节)
jmp do_jump
level2:
mov bx, 4       ; 对应branch3在跳转表中的索引2
jmp do_jump
level3:
mov bx, 6       ; 对应branch4在跳转表中的索引3

do_jump:
; 使用跳转表进行跳转
jmp jmp_table[bx]

branch1:  
mov ah,'A'
jmp finish
branch2: 
mov ah,'B'
jmp finish
branch3: 
mov ah,'C'
jmp finish
branch4:
mov ah,'D'

finish:      
mov grade, ah  
; 显示结果
mov dx, offset disp
mov ah, 9
int 21h    

MOV AH,4CH
INT 21H

CODE ENDS
END START

5.3 带输入的条件分支判断法。

DATA SEGMENT
  buf   db 3		;缓冲区长度
          db ?		;实际输入个数
  str1  db 3 DUP(?)	;存储空间

  score db 87
  disp   db 0dh, 0ah
  grade db ?,'$'

DATA ENDS

STACK1 SEGMENT PARA STACK
DW 40H DUP(?)
STACK1 ENDS

CODE SEGMENT
	ASSUME CS:CODE , DS:DATA
START:	MOV AX,DATA
	MOV DS,AX
mov dx, offset buf
mov ah, 0ah
int 21h

;=(str1[0]-'0')*10+(str1[1]-'0')=
mov al, str1[0]
sub al,'0'
mov bl, 10
mul bl
mov bl, str1[1]
sub bl, '0'
add al, bl

;mov al,score
cmp al,90
jge branch1
cmp al,80
jge branch2
cmp al,70
jge branch3
mov ah,'D'
jmp finish
branch1:  mov ah,'A'
	jmp finish
branch2: mov ah,'B'
	jmp finish
branch3: mov ah,'C'
	jmp finish
finish:
    mov grade, ah       ; 存储等级字符到内存
    mov dx, offset disp ; 设置要显示的字符串地址
    mov ah,9            ; 功能号9:显示字符串
    int 21h             ; 调用DOS中断显示结果
    
MOV AH,4CH              ; 功能号4Ch:程序结束
INT 21H                 ; 调用DOS中断结束程序

CODE ENDS
END START

6.1 利用循环——统计字符串中各类字符的个数

  • A:统计大写字母的个数
  • B:统计小写字母的个数
  • C:统计数字的个数
  • D:统计其他字符的个数
DATA SEGMENT
A DB 0
B DB 0
C DB 0
D DB 0
STRING DB 'ABBC34234a'
COUNT EQU $-STRING
DATA ENDS
STACK1 SEGMENT PARA STACK
DW 20H DUP(?)
STACK1 ENDS
CODE SEGMENT
ASSUME CS:CODE , DS:DATA
START:	
MOV AX,DATA
MOV DS,AX
MOV CX,COUNT   ;处理字符的个数CX = 字符串长度(10)
MOV SI,0
AGAIN:	
MOV AL,STRING[SI]
CMP AL,'A'
JB NEXT1		
CMP AL,'Z'
JBE RES1
NEXT1:	
CMP AL,'a'
JB NEXT2
CMP AL,'z'
JBE RES2
NEXT2:	
CMP AL,'0'
JB NEXT3
CMP AL,'9'
JBE RES3
NEXT3:	
INC D
JMP FIN
RES1:	
INC A
JMP FIN
RES2:	
INC B
JMP FIN
RES3:	
INC C
JMP FIN
FIN:	
INC SI
LOOP AGAIN ;CX--
MOV AH,4CH
INT 21H
CODE ENDS
END START
thanks.

友情提示

哎呀,主包的博客还没有很多朋友呢,快来加入我的友链队伍吧!