アセンブリ言語のcmp命令
アセンブリ言語のcmp命令は、次の命令とセットになってある場所にジャンプするものと思ってないか。
例えば、
cmp dl,dh
je yes
は、"cmp dl,dh"は次の"je yes"とセットになって「dlの数値とdhの数値が同じであればyesという所にジャンプする」命令と思ってないか。
それは違う。"cmp dl,dh"はdlの数値とdhの数値とを比較しその結果をある所に格納するものであり、je yesはある所に格納されている結果がイコールであればyesにジャンプするものである。
なので、"cmp dl,dh"と"je yes"との間に好きな命令を挟むことができる。
そんなcmp命令を利用したアセンブリ言語プログラムがこれ。
bits 16
org 0x100
;Aの数値を入力
mov ah,9
mov dx,msg1
int 21h
mov ah,8
int 21h
mov ah,02
mov dl,al
int 21h
mov ch,al
mov al,0
mov ah,9
mov dx,crlf
int 21h
;Bの数値を入力
mov ah,9
mov dx,msg2
int 21h
mov ah,8
int 21h
mov ah,02
mov dl,al
int 21h
mov cl,al
mov al,0
mov ah,9
mov dx,crlf
int 21h
;AとBの数値の比較
sub cx,3030h ;cxレジスタ内の各数字をそれぞれ数値に
cmp ch,cl ;ch内の数値(A)とcl内の数値(B)を比較
mov ah,9
mov dx,msg3
int 21h
mov dx,crlf
int 21h
;AはBよりも?
jg more ;大きければmoreへ
jl less ;小さければlessへ
;AとBが等しい場合
mov ah,9
mov dx,msg6
int 21h
jmp exit
;AとBが等しくない場合
more:
mov ah,9
mov dx,msg4
int 21h
jmp exit
less:
mov ah,9
mov dx,msg5
int 21h
;プログラム終了シーケンス
exit:
mov ah,4Ch
mov al,0
int 21h
;文字列データ群
msg1 db "A:$"
msg2 db "B:$"
msg3 db "A and B were compared.$"
msg4 db "A>B$"
msg5 db "A<B$"
msg6 db "A=B$"
crlf db 0dh,0ah,"$" ;改行用
Aに入力できる数値とBに入力できる数値はそれぞれ1桁の10進数のみ。
Aの数値とBの数値をcmp命令で比較した後、"A and B were compared."という文字列が出る。
その後、そのcmp命令での比較の結果に応じた出力がされる("A>B"と"A<B"と"A=B"のいずれかが画面に出る)。
割り算の答えを帯分数で表すアセンブリ言語プログラム
bits 16
org 0x100
mov ah,08h
int 21h
mov cl,al
mov ah,02
mov dl,cl
int 21h
mov ah,02
mov dl,'/'
int 21h
mov ah,08h
int 21h
mov ch,al
mov ah,02
mov dl,ch
int 21h
push cx
sub cx,3030h
mov ax,0
mov al,cl
mov cl,ch
mov ch,0
div cl
mov cx,ax
mov ax,0
cmp ch,0
jne tai
mov ah,9
mov dx,crlf
int 21h
mov ah,02
mov dl,'='
int 21h
add cl,30h
mov dl,cl
int 21h
jmp exit
tai:
mov ah,9
mov dx,crlf
int 21h
mov ah,02
mov dl,' '
int 21h
add ch,30h
mov dl,ch
int 21h
mov ah,9
mov dx,crlf
int 21h
mov ah,02
add cl,30h
mov dl,cl
int 21h
mov dl,'-'
int 21h
mov ah,9
mov dx,crlf
int 21h
mov ah,02
mov dl,' '
int 21h
pop cx
mov dl,ch
int 21h
exit:
mov ah,4Ch
mov al,0
int 21h
crlf db 0dh,0ah,"$"
入力できるのは1ケタの10進数のみ。
某フリー画像をアプリにすると?
このフリー画像を「BINファイル」にして逆アセンブルしたやつの一部がこれ(全部だとすごく長いから)。
000770C0 0821 or [bx+di],ah
000770C2 8410 test [bx+si],dl
000770C4 42 inc dx
000770C5 0821 or [bx+di],ah
000770C7 8410 test [bx+si],dl
000770C9 42 inc dx
000770CA C88B81FF enter 0x818b,0xff
000770CE 0F792B vmwrite ebp,dword [bp+di]
000770D1 B5FC mov ch,0xfc
000770D3 9C pushf
000770D4 F0EC lock in al,dx
000770D6 CD00 int 0x0
000770D8 0000 add [bx+si],al
000770DA 004945 add [bx+di+0x45],cl
000770DD 4E dec si
000770DE 44 inc sp
000770DF AE scasb
000770E0 42 inc dx
000770E1 60 pusha
000770E2 82 db 0x82
そして本フリー画像を拡張子をcomにしたやつを「DOSBox 0.74-3」上で起動すると?
「DOSBox 0.74-3」の画面が消えた!
そう、本フリー画像は「DOSBox 0.74-3」を閉じる(シャットダウン)アプリになるのである。
素数判定プログラムのアセンブリ言語コード
bits 16
org 100h
mov ah,0ah
mov dx,buf
mov byte [buf],20h
int 21h
mov dx,crlf
mov ah,09h
int 21h
mov dl,[buf+1]
cmp dl,1h
je one_digit
cmp dl,2h
je two_digits
jmp exit
one_digit:
mov dl,[buf+2]
sub dl,30h
jmp prime_judge
two_digits:
mov ax,[buf+2]
sub ax,30h
mov cx,0ah
mul cx
mov dx,ax
mov ax,[buf+3]
sub ax,30h
add dl,al
prime_judge:
mov ax,0
mov cx,0
mov cl,dl
cmp cl,0
je no
dec cl
cmp cl,0
je no
search:
mov ax,0
cmp cl,1
je yes
mov al,dl
div cl
cmp ah,0
je no
loop search
yes:
mov ax,0
mov ah,9
mov dx,msg1
int 21h
jmp exit
no:
mov ax,0
mov ah,9
mov dx,msg2
int 21h
exit:
mov ah,4Ch
mov al,0
int 21h
buf db " $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
crlf db 0dh,0ah,"$"
msg1 db "It is a prime.$"
msg2 db "It is not a prime.$"
入力できるのは1桁の数値と2桁の数値だけで、入力した数値が素数なら"It is a prime."という文字列が出、入力した数値が素数でなければ"It is not a prime."という文字列が出る。
擬似命令dbにより文字列のデータが存在するアセンブリ言語プログラムを逆アセンブルすると?
bits 16
org 0x100
mov ah,9
mov dx,msg
int 21h
mov ah,4Ch
mov al,0
int 21h
msg db "Hello.$"
00000000 B409 mov ah,0x9
00000002 BA0D01 mov dx,0x10d
00000005 CD21 int 0x21
00000007 B44C mov ah,0x4c
00000009 B000 mov al,0x0
0000000B CD21 int 0x21
0000000D 48 dec ax
0000000E 656C gs insb
00000010 6C insb
00000011 6F outsw
00000012 2E cs
00000013 24 db 0x24
になる。
最初の"bits 16"と"org 0x100"が消されているのは良い。何とも合理的だ。
問題は文字列のデータの部分。
アドレスDにおける"dec ax"はHを意味し、アドレスEとアドレスFにおける"gs insb"はelを意味し、アドレス10における"insb"はlを意味し、アドレス11における"outsw"はoを意味し、アドレス12における"cs"は.を意味し、アドレス13における"db 0x24"は$を意味する。
逆アセンブルすれば文字列が命令として扱われるのだ。