期末復習のまとめ... 本当に一生懸命復習しています...
実験の先生が私たちにやらせたあのいくつかの実験、考えてみると感謝しています~
入力と出力、分岐フロー、基本命令について話し、さらにやったいくつかの問題についても話します。
入力出力#
整数の ASCII コード値を数値に変換#
- 0-9 30H-39H
30H を引くか、1111 (15) と論理積を取ることができます。 - A-F 41H-46H
37H (55) を引きます。 - a-z 61H-66H
57H (75) を引きます。
一桁の 16 進整数を入力#
IN_1_HEX:
MOV AH, 01H
INT 21H ;入力された値はALに格納されます
CMP AL, '9' ;入力された値はメモリ内でASCIIコードの値で表されます
JBE IN
SUB AL, 07H
IN:
SUB AL, 30H
二桁の 16 進整数を入力#
二桁の 16 進数で表される値は最大で FF
、つまり 255 で、8 ビットで保存できます。
IN_2_HEX:
CALL IN_1_HEX ;高位16進数->AL
MOV AH, 10H
MUL AH
MOV AH, AL
CALL IN_1_HEX ;低位16進数->AL
ADD AL, AH
一桁の 10 進整数を入力#
実際に使用する際は、以前のデータを保護することを忘れず、まず PUSH してから POP します。
IN_1_DEC:
MOV AH, 01H ;AL
INT 21H
SUB AL, 30H
二桁の 10 進整数を入力#
IN_2_DEC:
CALL IN_1_DEC
MOV AH, 10 ; 16進数では10H
MUL AH
MOV AH, AL
CALL IN_1_DEC
ADD AL, AH
一桁の 16 進整数を出力#
DISP_1_HEX:
CMP DL, 09H
JBE L1
ADD DL, 07H
L1:
ADD DL, 30H
MOV AH, 02H
INT 21H
二桁の 16 進整数を出力#
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
一桁の 10 進整数を出力#
DISP_1_DEC:
PUSH AX
ADD DL,30H
MOV AH,02H
INT 21H
POP AX
RET
二桁の 10 進整数を出力#
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
符号付きの多桁 10 進整数を出力#
DISP: ; AXの数を10進数で出力
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 ; 商が0かどうか
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
ループ分岐構造#
比較#
最も重要なのは比較です。
TEST
、AND
、CMP
、SUB
などなど... すべて比較に使えます。
TEST 命令#
命令形式:TEST DST, SRC
TEST
命令は特定のビットが 1 かどうかを検出するために使用できます。なぜなら、その本質は論理積であり、DST & SRC
だからです。しかし、ソースオペランドとターゲットオペランドは変更しません。
例えば 00010000 & X
の結果は、X の倒数第五ビットが 1 かどうかを示します。もし論理積の結果が 0 であれば、そのビットは 0 であり、そうでなければ 1 です。
CMP 命令#
命令形式:CMP DST, SRC
2 つの数の大きさを比較できます。本質的には減算であり、DST - SRC
ですが、ソースオペランドとターゲットオペランドは変更しません。
ジャンプ命令#
ここでは、比較された 2 つの数の具体的な大きさを判断し、どの命令を実行するかを決定します。
C スタイルの言語では次のようになります:
if (a > b){
// a > b の場合はここを実行
}else{
// a <= b の場合はここを実行
}
アセンブリでは次のようになります:
CMP AX, BX
JA AGB
# AX <= BX の場合はここを実行
AGB:
# AX > BX の場合はここを実行
上記の JA
はジャンプ命令の一つです。その他の詳細な命令については、書籍を参照してください~
以下にいくつか覚えておくべき命令を少し紹介します~
- JE 2 つの数が等しい
- JNE 2 つの数が等しくない
- JA 無符号 前者が後者より大きい
私はこう覚えています。A は 2 つの比較の数の前者、B は後者なので、JA
は前者が大きいことを示します。 - JG 符号付き比較、前者が後者より大きい
G は greater than の意味です。 - JB 無符号 前者が後者より小さい
- JL 符号付き比較 前者が後者より小さい
L = less than - JAE 無符号大なりイコール
- JGE 符号付き大なりイコール
- JBE 無符号小なりイコール
- JLE 符号付き小なりイコール
二進数を十六進数に変換#
私たちは一桁の 16 進数が 4 桁の二進数を表すことを知っています。したがって、二進数を 16 進数に変換するには、4 桁ごとに変換する必要があります。
大まかな流れは次のようになります。
digraph g {
ループ左移動四桁の二進数
-> 低四桁を取得
-> "低四桁+30H"
-> 低四桁を出力;
低四桁を出力 -> ループ左移動四桁の二進数 [label="ビット数が0でない場合"]
}
制御転送命令#
書籍の P85
問題#
20 桁の符号付き 16 進数を入力し、ソート後に 10 進数の最大数、最小数、次大きい数、次小さい数を出力#
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