野声

Hey, 野声!

谁有天大力气可以拎着自己飞呀
twitter
github

IBM-PC 汇编语言程序设计复习

期末复习汇编... 真的是好努力的复习...
实验老师让我们做的那几个实验,想想还觉得谢谢了~
谈一下输入输出、分支流程、基本指令,再谈一下做过的几个题目。

输入输出#

整数的 ASCII 码值转为数值#

  • 0-9 30H-39H
    可以减去 30H 或者 与上 1111 (15)
  • A-F 41H-46H
    减去 37H (55)
  • a-z 61H-66H
    减去 57H (75)

输入一位十六进制整数#

IN_1_HEX:
	MOV AH, 01H
	INT 21H     ;输入的值存在AL里
	CMP AL, '9' ;输入的值在内存中都是以ASCII码的值表示
	JBE IN
	SUB AL, 07H
IN:
	SUB AL, 30H

输入两位十六进制整数#

两位十六进制表示的值最多是 FF ,也就是 255,用八位就可以存下。

IN_2_HEX:
	CALL IN_1_HEX ;高位十六进制->AL
	MOV  AH, 10H
	MUL  AH
	MOV  AH, AL
	CALL IN_1_HEX ;低位十六进制->AL
	ADD  AL, AH

输入一位十进制整数#

实际使用的时候记得要保护之前的数据,先 PUSH 再 POP

IN_1_DEC:
	MOV AH, 01H ;AL
	INT 21H
	SUB AL, 30H

输入两位十进制整数#

IN_2_DEC:
	CALL IN_1_DEC
	MOV  AH, 10  ; 十六进制这里为10H
	MUL  AH
	MOV  AH, AL
	CALL IN_1_DEC
	ADD  AL, AH

输出一位十六进制整数#

DISP_1_HEX:
  CMP DL, 09H
  JBE L1
  ADD DL, 07H
L1:
  ADD DL, 30H

  MOV AH, 02H
  INT 21H

输出两位十六进制整数#

DISP_2_HEX:
  MOV AL, DL
  MOV AH, 0
  MOV DL, 10H
  DIV DL        ; 除数是 8 位 AL 存商, AH 存余数
  MOV DL, AL
  CALL DISP_1_HEX
  MOV DL, AH
  CALL DISP_1_HEX

输出一位十进制整数#

DISP_1_DEC:
  PUSH AX
  ADD DL,30H
  MOV AH,02H
  INT 21H
  POP AX
RET

输出两位十进制整数#

DISP_2_DEC:    ; DL 除十取余法
  PUSH AX
  MOV AL,DL
  MOV AH,0
  MOV DL,10
  DIV DL        ; 除数是 8 位 AL 存商, AH 存余数
  MOV DL,AL
  CALL DISP_1_DEC
  MOV DL,AH
  CALL DISP_1_DEC
  POP AX
RET

带符号位的输出多位十进制整数#

DISP:            ; 用十进制出AX中的数
  PUSHF
  PUSH DX
  PUSH AX
  PUSH BX
  PUSH CX

  MOV  CX, 0
  MOV  BX, 10    ; 除 10 取余法

  TEST AX, 8000H ; 检测AX首位是1还是0
  JE   DISP1     ; 如果上一句的结果为0,就跳
  CALL FF        ; 输出负号
  NEG  AX        ; 取反+1

DISP1:
  MOV  DX, 0
  DIV  BX        ;除数是 16 位 AX,商;DX,余数
  PUSH DX
  INC  CX
  OR   AX, AX    ; 是否商完
  JNE  DISP1     ; 没商完继续商

DISP2:
  POP  DX
  ADD  DL, 30H   ; 以ascii码输出
  MOV  AH, 02H
  INT  21H
  LOOP DISP2

  POP  CX
  POP  BX
  POP  AX
  POP  DX
  POPF
RET
FF:
  PUSH DX
  PUSH AX

  MOV  DL, '-'
  MOV  AH, 02H
  INT  21H

  POP  AX
  POP  DX
RET

循环分支结构#

比较#

最重要的就是 比较,

TESTANDCMPSUB 还有等等等等... 都可以拿来做比较。

TEST 指令#

指令格式:TEST DST, SRC
TEST 指令可以被用来检测某一位是否为 1,因为其本质就是与运算,也就是 DST & SRC,但是不改变源操作数和目标操作数。

00010000 & X 的结果就表示 X 的倒数第五位是否为 1,要是与出来为 0,就说明这一位为 0,否则为 1。

CMP 指令#

指令格式:CMP DST, SRC

可以比较两个数的大小,本质就是减法运算,也就是 DST - SRC,但是不改变源操作数和目标操作数。

跳转指令#

这里的就是判断被比较的两个数的具体大小,然后决定执行哪一句。

C-style 的语言中是这样:

if (a > b){
  // a > b 的话执行这儿
}else{
  // a <= b 的话执行这儿
}

汇编中呢,就是:

  CMP AX, BX
  JA AGB
  # AX <= BX 的话执行这儿
AGB:
  # AX > BX 的话执行这儿

上面的 JA 就是一个跳转指令,再详细的各种指令我就不说了,看书~
下面稍微说几个记得牢的~

  • JE 两个数相等
  • JNE 两个数不相等
  • JA 无符号 前者大于后者
    我是这样记得, A 就是两个比较的数里前面那个,B 就是两个比较的数里后面那个,所以 JA 就是前面的大。
  • JG 有符号比较,前者大于后者
    G 的意思就是 greater than
  • JB 无符号 前者小于后者
  • JL 有符号比较 前者小于后者
    L = less than
  • JAE 无符号大于等于
  • JGE 有符号大于等于
  • JBE 无符号小于等于
  • JLE 有符号小于等于

二进制转十六进制#

我们都知道,一位十六进制可以表示四位二进制,所以要把二进制转为十六进制的画,得每四位每四位的转换。
大概流程如下

digraph g {
循环左移四位二进制
	-> 取低四位
	-> "低四位+30H"
	-> 输出低四位;

输出低四位 ->循环左移四位二进制 [label="如果位数不为0"]
}

控制转移指令#

书上 P85

题目#

输入二十位带符号十六进制数,排序后输出十进制最大数、最小数、次大数、次小数#

DATA SEGMENT
  X  DW 20 DUP(?)
  NUM DW 6
DATA ENDS
S1 SEGMENT PARA STACK
  BUF1 DW 20H DUP (0)
  LEN1 EQU $-BUF1
S1 ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:S1
GO:
  MOV  AX,DATA
  MOV  DS,AX
  MOV  AX,S1
  MOV  SS,AX
  MOV  SP,LEN1

  MOV  CX,NUM
  MOV  SI,OFFSET X

L1:
  CALL IN_2_HEX
  MOV  AH, AL
  CALL IN_2_HEX
  MOV  [SI],AX
CC:
  CALL SPACE
  ADD  SI,2
  LOOP L1
  CALL HR
  MOV CX,NUM
  MOV SI,OFFSET X
  DEC CX

LOOP1:
  PUSH CX
  MOV BX,OFFSET X
LOOP2:
  MOV AX,[BX]
  CMP AX,[BX+2]
  JGE CONTINUE     ;有符号比较
  XCHG AX,[BX+2]
  MOV [BX],AX
CONTINUE:
  ADD BX,2
  LOOP LOOP2
  POP CX
  LOOP LOOP1
  MOV cx, NUM
  MOV si,offset X
  CALL HR

dispdec2:
  MOV AX,[si]
  call DISP
  call SPACE
  add si,2
  loop dispdec2
  CALL HR

  MOV si,offset X
  CALL HR

  ; 最小数
  DEC NUM
  SHL NUM, 1
  ADD SI,NUM
  MOV AX,[SI]
  call DISP
  call SPACE

  ; 最大数
  MOV si,offset X
  MOV AX,[si]
  call DISP
  call SPACE

  ; 次小数

  ADD SI,NUM
  MOV AX,[SI-2]
  call DISP
  call SPACE

  ; 次大数
  MOV si,offset X
  MOV AX,[SI+2]
  call DISP
  call HR

  MOV AH,4CH
  INT 21H

IN_2_HEX:
  PUSHF
  PUSH BX
  MOV BH,AH
  CALL IN_1_HEX  ;AL  high
  MOV AH,10H
  MUL AH ;
  MOV AH,AL
  CALL IN_1_HEX  ;AL  low
  ADD AL,AH
  MOV AH,BH
  POP BX
  POPF
RET

IN_1_HEX:
  PUSHF
  PUSH BX
  MOV BH,AH

  MOV AH,01H
  INT 21H

  cmp AL,'9'
  JBE IN_B
  SUB AL,07H
IN_B:   ; 'A-F'
  SUB AL,30H
  MOV AH,BH
  POP BX
  POPF
RET


DISP:
  PUSHF
  PUSH DX
  PUSH AX
  PUSH BX
  PUSH CX

  MOV CX,0
  MOV BX,10

  test AX,8000H;是否为负
  JE DISP1
  CALL FF
  ;AND  AX,7FFFH
  NEG  AX

DISP1:
  MOV DX,0
  DIV BX     ;AX,商;DX,余数
  PUSH DX
  INC CX
  OR AX,AX   ;是否为0
  JNE DISP1
DISP2:
  MOV AH,2
  POP DX
  ADD DL,30H
  INT 21H
  LOOP DISP2
  POP CX
  POP BX
  POP AX
  POP DX
  POPF
RET


SPACE:
  PUSH DX
  PUSH AX
  MOV  DL,20H
  MOV  AH,02H
  INT  21H
  POP  AX
  POP  DX
RET

HR:
  PUSH AX
  PUSH DX
  MOV  AH,02H
  MOV  DL,0AH
  INT  21H
  MOV  DL,0DH
  INT  21H
  POP  DX
  POP  AX
RET
FF:
  PUSH DX
  PUSH AX
  MOV  DL,'-'
  MOV  AH,02H
  INT  21H
  POP  AX
  POP  DX
RET
CODE ENDS
END GO
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。