10. x86アセンブリ処理とフローチャート

ここでは、x86アセンブリ処理とフローチャートの対応関係について書きます。ソースコードとフローチャートを順番に書くことで、x86アセンブリ処理の流れを明確にします。※アセンブラはNASM、Windows用リンカはalink、ライブラリはwin32.libを利用します。

10.1. goto文

x86アセンブリではジャンプ命令を多用します。

gotoの構文

jmp ジャンプ先アドレス
;「ジャンプ先アドレス」はラベル、レジスタなどアドレスをあらわすものが来ます。
goto文例
as_goto.asm
	org 100H
section .text

START:
	jmp B
A:
	mov bx, P01
	call PRINT

B:
	mov bx, P02
	call PRINT
	jmp D

C:
	mov bx, P03
	call PRINT

D:
	;プログラムの終了
	mov ah, 4cH
	int 21H


;表示関数
PRINT:
	mov ax, 0200H
	mov dl, [ds:bx]
	cmp dl, 00H
	jz PRINTEND
	int 21H ;システムコール
	inc bx
	jmp PRINT
PRINTEND:
	ret

	
section .data ;データセクション
P01 db '01',00H
P02 db '02',00H
P03 db '03',00H

goto文例のフローチャート

_images/bat_goto_ex.gif

10.2. 三項の条件演算子

バッチ処理には、この構文はありません。
別の節で説明するif...else文を参照してください。

※参考:Javaの 三項の条件演算子への参照


10.3. if...else文

※参考:Javaの if...else文への参照

if...else文は無いですが、cmp命令とj*命令を組み合わせて使うことで同様の処理が可能です。

cmp、j*の構文

;===========================
;符号あり
;===========================

;dest:ジャンプ先アドレス

;if(A == B) goto dest
cmp A, B
je dest

;if(A < B) goto dest
cmp A, B
jg dest

;if(A <= B) goto dest
cmp A, B
jle dest

;if(A > B) goto dest
cmp A, B
jg dest

;if(A >= B) goto dest
cmp A, B
jge dest

;not
;===========================

;if(!(A == B)) goto dest
;if(A != B) goto dest
cmp A, B
jne dest

;if(!(A < B)) goto dest
cmp A, B
jnl dest

;if(!(A <= B)) goto dest
cmp A, B
jnle dest

;if(!(A > B)) goto dest
cmp A, B
jng dest

;if(!(A >= B)) goto dest
cmp A, B
jnge dest

;===========================
;符号なし
;===========================

;dest:ジャンプ先アドレス

;if(A == B) goto dest
cmp A, B
je dest

;if(A < B) goto dest
cmp A, B
jb dest

;if(A <= B) goto dest
cmp A, B
jbe dest

;if(A > B) goto dest
cmp A, B
ja dest

;if(A >= B) goto dest
cmp A, B
jae dest

;not
;===========================

;if(!(A == B)) goto dest
;if(A != B) goto dest
cmp A, B
jne dest

;if(!(A < B)) goto dest
cmp A, B
jnb dest

;if(!(A <= B)) goto dest
cmp A, B
jnbe dest

;if(!(A > B)) goto dest
cmp A, B
jna dest

;if(!(A >= B)) goto dest
cmp A, B
jnae dest

if..else文例

as_if_else.asm

	org 100H

;非初期化データセクション(変数として使う)
section .bss
	age: resw 1     ;short int age
	result: resw 1  ;short int result 

section .text
START:
	mov [ds:age], word 116
	mov [ds:result], word 0
	
	if00: ;if(age>=70)
		cmp [ds:age], word 70
		jge then01
		jmp elseif01
	then01:
		mov [ds:result], word STR01
		jmp endif00
	elseif01: ;else if(age>=60)
		cmp [ds:age], word 60
		jge then02
		jmp elseif02
	then02:
		mov [ds:result], word STR02
		jmp endif00
	elseif02: ;else if(age>=50)
		cmp [ds:age], word 50
		jge then03
		jmp elseif03
	then03:
		mov [ds:result], word STR03
		jmp endif00
	elseif03: ;else if(age>=40)
		cmp [ds:age], word 40
		jge then04
		jmp elseif04
	then04:
		mov [ds:result], word STR04
		jmp endif00
	elseif04: ;else if(age>=30)
		cmp [ds:age], word 30
		jge then05
		jmp elseif05
	then05:
		mov [ds:result], word STR05
		jmp endif00
	elseif05: ;else if(age>=15)
		cmp [ds:age], word 15
		jge then06
		jmp else06
	then06:
		mov [ds:result], word STR06
		jmp endif00
	else06:
		mov [ds:result], word STR07
		jmp endif00
	endif00:
	
	
	mov bx, [ds:result]
	call PRINT ;=>学に志す

	;プログラムの終了
	mov ah, 4cH
	int 21H


;表示関数
PRINT:
	mov ax, 0200H
	mov dl, [ds:bx]
	cmp dl, 00H
	jz PRINTEND
	int 21H ;システムコール
	inc bx
	jmp PRINT
PRINTEND:
	ret



;初期化データセクション
section .data 
	STR01 db '心の欲する所に従って矩を踰えず',00H
	STR02 db '耳順う',00H
	STR03 db '天命を知る',00H
	STR04 db '惑わず',00H
	STR05 db '立つ',00H
	STR06 db '学に志す',00H
	STR07 db '無し',00H

if..else文例のフローチャート

_images/rongo.gif

10.4. switch文

この構文はありません。しかし、「section .data」データセクションを使って類似の記述ができます。

構文

section .rodata
        定数(配列)名 サイズ 初期化値1 初期化値2 ...
        ;サイズ:dd、dw、db ディレクティブを使って、32ビット、16ビット、8ビットの値を宣言します。

jmp ジャンプ先アドレス

※参考:Javaの switch文への参照


switch文例

as_switch.asm

	org 100H

;非初期化データセクション 大域変数として使う
section .bss
	month: resw 1   ;shot int month
	result: resw 1  ;shot int result

section .text
START:
	mov [ds:month], word 2
	mov [ds:result], word 0

	mov ax, [ds:month]

	;switch(month)
	;範囲判定
	cmp ax, 1
	jl default0
	cmp ax, 12
	jg default0
	
	;caseへのジャンプ
	jmp [SW_CASES+(eax-1)*2]
	case1:
		mov [ds:result], word MONTH01
		jmp endswitch
	case2:
		mov [ds:result], word MONTH02
		jmp endswitch
	case3:
		mov [ds:result], word MONTH03
		jmp endswitch
	case4:
		mov [ds:result], word MONTH04
		jmp endswitch
	case5:
		mov [ds:result], word MONTH05
		jmp endswitch
	case6:
		mov [ds:result], word MONTH06
		jmp endswitch
	case7:
		mov [ds:result], word MONTH07
		jmp endswitch
	case8:
		mov [ds:result], word MONTH08
		jmp endswitch
	case9:
		mov [ds:result], word MONTH09
		jmp endswitch
	case10:
		mov [ds:result], word MONTH10
		jmp endswitch
	case11:
		mov [ds:result], word MONTH11
		jmp endswitch
	case12:
		mov [ds:result], word MONTH12
		jmp endswitch
	default0:
		mov [ds:result], word ERROR
		jmp endswitch
	endswitch:

	mov bx, [ds:result]
	call PRINT

	;プログラムの終了
	mov ah, 4cH
	int 21H




;表示関数
PRINT:
	mov ax, 0200H
	mov dl, [ds:bx]
	cmp dl, 00H
	jz PRINTEND
	int 21H ;システムコール
	inc bx
	jmp PRINT
PRINTEND:
	ret



;定数(const)を格納するためのセクション※read only data section
section .rodata
	;switch caseテーブル
	SW_CASES dw case1, case2, case3, case4, case5, case6, case7, case8, case9, case10, case11, case12, default0

	;文字列テーブル
	MONTH01 db 'January',00H
	MONTH02 db 'February',00H
	MONTH03 db 'March',00H
	MONTH04 db 'April',00H
	MONTH05 db 'May',00H
	MONTH06 db 'June',00H
	MONTH07 db 'July',00H
	MONTH08 db 'August',00H
	MONTH09 db 'September',00H
	MONTH10 db 'October',00H
	MONTH11 db 'November',00H
	MONTH12 db 'December',00H
	ERROR db 'err',00H

switch文例のフローチャート

_images/switch_ex.gif

10.5. for文

for文は無いので、ジャンプ命令、cmp命令を利用して類似の処理を行います。

※参考:Javaの for文への参照

1~10の合計を求めるfor文の例
as_for.asm
※sprintfを使うために32ビットWindowsプログラムとする
extern MessageBoxA
extern wsprintfA
extern ExitProcess

;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H       ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H   ;const char STR_TITLE[] = "Message"


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1  ; int sum
	i: resd 1    ; int i
	str: resb 64 ; char str[64]


section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	mov [ds:sum], dword 0

	;for(i=1;i<=10;i++)
		mov [ds:i], dword 1
	for01:
		cmp dword [ds:i], 10
		jle then01
		jmp endfor01
	then01:
		mov eax, dword [ds:i]
		add [ds:sum], dword eax
		
		inc dword [ds:i]
		jmp for01
	endfor01:
	;end for
	
	push dword [ds:sum]; PRINTNUM(sum)
	call PRINTNUM ;=>55
	sub esp, 4;PRINTNUM呼び出し引数スタック除去

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess;

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

for文例のフローチャート

_images/for_ex.gif

10.6. for-each文

for-each文は無いので、ジャンプ命令、com命令を利用して類似の処理を行います。

※参考:Javaの for each文への参照


1~10の合計を求めるfor文の例
as_for_each.asm
extern MessageBoxA
extern wsprintfA
extern ExitProcess

;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H        ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H    ;const char STR_TITLE[] = "Message"
	NUMS dd 1,2,3,4,5,6,7,8,9,10  ;const int NUMS[] = {1,2,3,4,5,6,7,8,9,10}


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1    ;int sum;
	i: resd 1      ;int i;
	str: resb 64   ;char str[64];


section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	mov [ds:sum], dword 0

	;for(i=0;i<10;i++)
		mov [ds:i], dword 0
	for01:
		cmp dword [ds:i], 10
		jl then01
		jmp endfor01
	then01:
		mov eax, dword [ds:i]
		mov ebx, [ds:NUMS+eax*4]
		add [ds:sum], dword ebx
		
		inc dword [ds:i]
		jmp for01
	endfor01:
	;end for
	
	push dword [ds:sum]; PRINTNUM(sum)
	call PRINTNUM ;=>55
	sub esp, 4;PRINTNUM呼び出し引数スタック除去

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess;

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

for each文例のフローチャート

_images/for_each.gif

10.7. while文

while文はありません。しかし、ジャンプ命令とcmp命令を使って類似の記述ができます。

※参考:Javaの while文への参照


1~10の合計を求める例
as_while.asm
extern MessageBoxA
extern wsprintfA
extern ExitProcess

;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H       ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H   ;const char STR_TITLE[] = "Message"


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1  ; int sum
	i: resd 1    ; int i
	str: resb 64 ; char str[64]


section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	;i=1
	mov [ds:i], dword 1
	;sum=0
	mov [ds:sum], dword 0

	;while(i<=10)
	while01:
		cmp dword [ds:i], 10
		jle then01
		jmp endwhile01
	then01:
		mov eax, dword [ds:i]
		add [ds:sum], dword eax

		inc dword [ds:i]
		jmp while01
	endwhile01:
	;end while
	
	push dword [ds:sum]; PRINTNUM(sum)
	call PRINTNUM ;=>55
	sub esp, 4;PRINTNUM呼び出し引数スタック除去

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess;

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

while文例のフローチャート

_images/while_ex.gif

10.8. do..while文

do..while文はありません。しかし、ジャンプ命令とcmp命令を使って類似の記述ができます。

※参考:Javaの do while文への参照


1~10の合計を求める例
as_do_while.asm
extern MessageBoxA
extern wsprintfA
extern ExitProcess

;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H       ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H   ;const char STR_TITLE[] = "Message"


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1  ; int sum
	i: resd 1    ; int i
	str: resb 64 ; char str[64]


section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	;i=1
	mov [ds:i], dword 1
	;sum=0
	mov [ds:sum], dword 0

	;do
	do01:
		mov eax, dword [ds:i]
		add [ds:sum], dword eax
		
		;i++
		inc dword [ds:i]

		cmp dword [ds:i], 10
		jle do01
	dowhile01:
	;while(i<=10)

	push dword [ds:sum]; PRINTNUM(sum)
	call PRINTNUM ;=>55
	sub esp, 4;PRINTNUM呼び出し引数スタック除去

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess;

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

do_while文例のフローチャート

_images/do_while_ex.gif

10.9. continue文

continue文は無いので、ジャンプ命令、cmp命令を利用して類似の処理を行います。

※参考:Javaの continue文への参照


as_for_continue.asm

extern MessageBoxA
extern wsprintfA
extern ExitProcess

;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H       ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H   ;const char STR_TITLE[] = "Message"


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1  ; int sum
	i: resd 1    ; int i
	str: resb 64 ; char str[64]


section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	mov [ds:sum], dword 0

	;for(i=1 ; i<=10 ; i++)
		mov [ds:i], dword 1
	for01:
		cmp dword [ds:i], 10
		jle then01
		jmp endfor01
	then01:
		cmp dword [ds:i], dword 3
		je continue01
		mov eax, dword [ds:i]
		add [ds:sum], dword eax

	continue01:
		;i++
		inc dword [ds:i]
		jmp for01
	endfor01:
	;end for

	push dword [ds:sum]
	;PRINTNUM(sum)
	call PRINTNUM ;=>52
	;PRINTNUM呼び出し引数スタック除去
	sub esp, 4

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

continue文例のフローチャート

_images/bat_for_continue_ex.gif

10.10. break文

break文は無いので、ジャンプ命令、cmp命令を利用して類似の処理を行います。

※参考:Javaの break文への参照


as_for_break.asm

extern MessageBoxA
extern wsprintfA
extern ExitProcess

;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H       ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H   ;const char STR_TITLE[] = "Message"


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1  ; int sum
	i: resd 1    ; int i
	str: resb 64 ; char str[64]

section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	mov [ds:sum], dword 0

	;for(i=1 ; i<=10 ; i++)
		mov [ds:i], dword 1
	for01:
		cmp dword [ds:i], 10
		jle then01
		jmp endfor01
	then01:
		mov eax, dword [ds:i]
		add [ds:sum], dword eax

		cmp dword [ds:sum], dword 30
		jge break01

		;i++
		inc dword [ds:i]
		jmp for01
	break01:
	endfor01:
	;end for

	push dword [ds:sum]
	;PRINTNUM(sum)
	call PRINTNUM ;=>36
	;PRINTNUM呼び出し引数スタック除去
	sub esp, 4; pop n

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess;

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

break文例のフローチャート

_images/bat_for_break_ex.gif

10.11. ラベル付きcontinue文

ラベル付きcontinue文は無いので、ジャンプ命令、cmp命令を利用して類似の処理を行います。

※参考:Javaの ラベルcontinue文への参照


as_for_double_continue.asm

extern MessageBoxA
extern wsprintfA
extern ExitProcess


;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H       ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H   ;const char STR_TITLE[] = "Message"


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1  ; int sum
	i: resd 1    ; int i
	j: resd 1    ; int j
	str: resb 64 ; char str[64]


section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	mov [ds:sum], dword 0

	;MYLABEL:for(i=1 ; i<=10 ; i++)
		mov [ds:i], dword 1
	for01:
		cmp dword [ds:i], 10
		jle then01
		jmp endfor01
	then01:
		;for(j=1 ; j<=10 ; j++)
			mov [ds:j], dword 1
		for02:
			cmp dword [ds:j], 10
			jle then02
			jmp endfor02
		then02:
			cmp dword [ds:i], dword 3
			je continue01; continue MYLABEL

			;sum = sum+i*j
			mov eax, dword [ds:i]
			mov ebx, dword [ds:j]
			mul ebx
			add [ds:sum], dword eax

			;j++
			inc dword [ds:j]
			jmp for02
		endfor02:
		;end for

	continue01:
		;i++
		inc dword [ds:i]
		jmp for01
	endfor01:
	;end for

	push dword [ds:sum]
	;PRINTNUM(sum)
	call PRINTNUM ;=>2860
	;PRINTNUM呼び出し引数スタック除去
	sub esp, 4; pop n

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess;

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

ラベル付きcontinue文例のフローチャート

_images/bat_for_double_continue_ex.gif

10.12. ラベル付きbreak文

ラベル付きbreak文は無いので、ジャンプ命令、cmp命令を利用して類似の処理を行います。

※参考:Javaの ラベルbreak文への参照


as_for_double_break.asm

extern MessageBoxA
extern wsprintfA
extern ExitProcess

;定数(const)を格納するためのセクション※read only data section
section .rodata 
	STR_FORMAT db '%d',00H       ;const char STR_FORMAT[] = "%d"
	STR_TITLE db 'Message',00H   ;const char STR_TITLE[] = "Message"


;非初期化データセクションを変数として使う
section .bss
	sum: resd 1  ; int sum
	i: resd 1    ; int i
	j: resd 1    ; int j
	str: resb 64 ; char str[64]

section .text
global main

main:
	;エントリーシーケンス
	push ebp
	mov ebp, esp

	;関数コード
	mov [ds:sum], dword 0

	;MYLABEL:for(i=1 ; i<=10 ; i++)
		mov [ds:i], dword 1
	for01:
		cmp dword [ds:i], 10
		jle then01
		jmp endfor01
	then01:

		;for(j=1 ; j<=10 ; j++)
			mov [ds:j], dword 1
		for02:
			cmp dword [ds:j], 10
			jle then02
			jmp endfor02
		then02:
			;sum = sum+i*j
			mov eax, dword [ds:i]
			mov ebx, dword [ds:j]
			mul ebx
			add [ds:sum], dword eax

			cmp dword [ds:sum], dword 15
			jge break01; break MYLABEL

			;j++
			inc dword [ds:j]
			jmp for02
		endfor02:
		;end for

		;i++
		inc dword [ds:i]
		jmp for01
	break01:
	endfor01:
	;end for

	push dword [ds:sum]
	;PRINTNUM(sum)
	call PRINTNUM ;=>15
	;PRINTNUM呼び出し引数スタック除去
	sub esp, 4; pop n

	;Windowsプログラムの終了ではExitProcessを呼ぶ
	call ExitProcess;

	;プログラムの終了
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret


;メッセージボックス表示関数
PRINTNUM:
	;エントリーシーケンス
	push ebp
	mov ebp, esp
	
	;関数コード
	
	;eax = 第1引数
	mov eax, [ebp+8]

	push dword eax
	;STR_FORMAT = "%d"
	push dword STR_FORMAT
	;strはchar[64]
	push dword str
	;sprintf(str,"%d",eax)
	call wsprintfA

	push dword 0
	push dword STR_TITLE
	push dword str
	push dword 0
	;MessageBoxA(0,str,"Message",0)
	call MessageBoxA
	
	;終了シーケンス
	mov esp, ebp
	pop ebp
	ret

ラベル付きbreak文例のフローチャート

_images/bat_for_double_break_ex.gif