Assembly Language
フロー制御
サーチ…
前書き
重要でないソフトウェアのすべてには、条件に応じてプログラムの流れをそらすためのフロー制御構造が必要です。アセンブリーは最低レベルのプログラミング言語であり、制御構造のプリミティブのみを提供します。通常、マシン操作はCPUのフラグに影響し、 条件分岐/ジャンプはフロー制御を実装します。アセンブリでは、すべての上位レベルの制御構造をそのようなプリミティブから構築する必要があります。
m68k組立での簡単なIF-THEN-ELSE
; IF d0 == 10 GO TO ten, ELSE GO TO other
CMP #10,d0 ; compare register contents to immediate value 10
; instruction affects the zero flag
BEQ ten ; branch if zero flag set
other:
; do whatever needs to be done for d0 != 10
BRA afterother ; unconditionally jump across IF case
ten:
; do whatever needs to be done for d0 == 10
afterother:
; continue normal common program flow
どの命令がどのフラグに影響を及ぼしているか、どの条件分岐(特定のフラグの組合せにも基づく可能性があります)が利用可能かは、選択したCPUによって大きく異なり、マニュアルで参照する必要があります。
FOR ...次のZ80アセンブリ
Z80には、ループカウントを実装するための特別な命令がありますDJNZ
は「Bレジスタをデクリメントし、ゼロでない場合にジャンプ」を表します。したがって、Bはこのプロセッサでループを実装するための選択レジスタです。 FOR ... NEXTは "後方に"実装する必要があります。なぜなら、レジスタはゼロまでカウントダウンするからです。他のCPU(8086のように、このCPUはループカウンタとしてCXレジスタを使用しています)には同様の特定のループカウンタレジスタと命令があります。
; Trivial multiplication (by repeated adding, ignores zero in factors, so
; not recommended for general use)
;
; inputs: A = Factor 1
; B = Factor 2
;
; output: A = Factor 1 * Factor 2
;
; Pseudo code
; C = A : A = 0 : FOR B = Factor 2 DOWNTO 0 : A = A + C : NEXT B
mul:
LD C,A ; Save Factor 1 in C register
XOR A ; Clear accumulator
mLoop:
ADD A,C ; Add Factor 1 to accumulator
DJNZ mLoop ; Do this Factor 2 times
RET ; return to caller
インテル構文アセンブリのIf文
section .data
msg_eq db 'Equal', 10
len_eq equ $ - msg_eq
msg_le db 'Less than', 10
len_le equ $ - msg_le
msg_gr db 'Greater than', 10
len_gr equ $ - msg_gr ; Length of msg_gr
section .text
global _main ; Make the _main label global for linker
_main:
cmp 4, 5 ; Compare 4 and 5
je _equal ; je = jump if equal
jl _less ; jl = jump if less
jg _greater ; jg = jump if greater
exit:
ret ; Return
_equal:
; Whatever code here
mov rax, 0x2000004 ; sys_write, 4 for linux
mov rdi, 1 ; STDOUT
mov rsi, msg_eq
mov rdi, len_eq
syscall
jmp exit ; Exit
_less:
; Whatever code here
mov rax, 0x2000004
mov rdi, 1
mov rsi, msg_le
mov rdi, len_le
syscall
jmp exit
_greater:
; Whatever code here
mov rax, 0x2000004
mov rdi, 1
mov rsi, msg_gr
mov rdi, len_gr
syscall
jmp exit
Intel構文アセンブリで条件が真である間にループする
section .data
msg db 'Hello, world!', 0xA
len equ $ - msg
section .text
global _main
_main:
mov rax, 0 ; This will be the current number
mov rcx, 10 ; This will be the last number
_loop:
cmp rax, rcx
jl .loopbody ; Jump to .loopbody if rax < rcx
jge _exit ; Jump to _exit if rax ≥ rcx
.loopbody:
push rax ; Store the rax value for later use
mov rax, 0x2000004 ; 4 for Linux
mov rdi, 1 ; STDOUT
mov rsi, msg
mov rdx, len
syscall
pop rax ; Take it back to rax
inc rax ; Add 1 to rax. This is required since the loop must have an ending.
jmp _loop ; Back to loop
_exit:
ret ; Return
rax < rcx
あれば.loopbody
を実行します。
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow