野声

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) を引きます。

一桁の 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

ループ分岐構造#

比較#

最も重要なのは比較です。

TESTANDCMPSUB などなど... すべて比較に使えます。

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
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。