저희 컴퓨터는 윈7 64bit 이고
gcc 깔아서 하고 있는데 자꾸 오류가 나네요
제 생각엔 32bit 때문인 것 같기도 하고 아니면 코드 상의 오류 인 것 같기도 하고..
일단 asm_io.asm 랑 asm_io.inc는 폴 카터 홈페이지에서 다운 받고 asm_io.o 도 그렇고요
(혹시나해서 nasm -f coff asm_io.asm 해서 o파일 만들어도 안 되네요)
driver.c 랑 first.asm 은 그 pdf 파일에 있는 것 보고 제가 타이핑 했습니다.
driver.c 를 o파일 만들 때 gcc -c driver.c 를 사용 했고
first.asm 을 o파일 만들 때는 nasm -f coff fisrt.asm 을 사용했습니다.
그리고 exe 파일 만들 때는 gcc -o first first.o driver.o asm_io.o 를 했는데
~~~~(생략)~~~~ i386 architecture of input file 'first.o' is incompatible with i386:x86-64 output
~~~~(생략)~~~~ i386 architecture of input file 'asm_io.o' is incompatible with i386:x86-64 output
first.o:first.asm:<.text+0xb>: undefined reference to 'print_string'
first.o:first.asm:</text+0x10>: undefined reference to 'read_int'
~~~~(생략)~~~~ first.o: bad reloc address 0x10 in section '.text'
~~~~(생략)~~~~ final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
라고 에러가 뜨네요
이제 코드 올리겠습니다.
1. first.asm
; file: first.asm
; 최초의 어셈블리 프로그램. 이 프로그램은 2 개의 정수를 입력받아
; 그 합을 출력한다.
;
; 실행 가능한 프로그램을 만들려면 DJGPP를 이용해라 :
; nasm -f coff first.asm
; gcc -o first first.o driver.c asm_io.o
%include "asm_io.inc"
;
; 초기화 된 데이터는 .data 세그먼트에 들어간다.
segment .data
;
; 아래 라벨들은 출력을 위한 문자열들을 가리킨다.
;
prompt1 db "Enter a number: ", 0 ;널 종료 문자임을 잊지 말라!
prompt2 db "Enter another number: ", 0
outmsg1 db "You entered ", 0
outmsg2 db " and ", 0
outmsg3 db ", the sum of these is ", 0
;
;초기화 되지 않은 데이터는 .bss 세그먼트에 들어간다.
;
segment .bss
;
; 이 라벨들은 입력 값들을 저장하기 위한 더블워드를 가리킨다.
input1 resd 1
input2 resd 1
;
; 코드는 .text 세그먼트에 들어간다.
segment .text
global _asm_main
_asm_main:
enter 0,0 ;셋업(set up) 루틴
pusha
mov eax, prompt1 ; prompt를 출력
call print_string
call read_int ;정수를 읽는다.
mov [input1], eax ;input1에 저장
mov eax, prompt2 ;prompt를 출력
call print_string
call read_int ;정수를 읽는다.
mov [input2], eax ;input2에 저장
mov eax, [input1] ; eax = input1 에 위치한 dword
add eax, [input2] ; eax += input2 에 위치한 dword
mov ebx, eax ;ebx = eax
dump_regs 1 ;레지스터의 값을 출력
dump_mem 2, outmsg1, 1 ;메모리를 출력
;
;아래 단계별로 메세지를 출력한다.
;
mov eax, outmsg1
call print_string ;첫 번째 메세지를 출력
mov eax, [input1]
call print_int ;input1을 출력
mov eax, outmsg2
call print_string ;두 번째 메세지를 출력
mov eax, [input2]
call print_int ;input2를 출력
mov eax, outmsg3
call print_string ;세 번째 메세지를 출력
mov eax, ebx
call print_int ;합을 출력 (ebx)
call print_nl ;개행문자를 출력
popa
mov eax, 0 ;c로 리턴된다.
leave
ret
2.driver.c
int main()
{
int ret_status ;
ret_status = asm_main();
return ret_status ;
}
3.asm_io.asm
;
; file: asm_io.asm
; Assembly I/O routines
; To assemble for DJGPP
; nasm -f coff -d COFF_TYPE asm_io.asm
; To assemble for Borland C++ 5.x
; nasm -f obj -d OBJ_TYPE asm_io.asm
; To assemble for Microsoft Visual Studio
; nasm -f win32 -d COFF_TYPE asm_io.asm
; To assemble for Linux
; nasm -f elf -d ELF_TYPE asm_io.asm
fine NL 10
fine CF_MASK 00000001h
fine PF_MASK 00000004h
fine AF_MASK 00000010h
fine ZF_MASK 00000040h
fine SF_MASK 00000080h
fine DF_MASK 00000400h
fine OF_MASK 00000800h
;
; Linux C doesn't put underscores on labels
;
%ifdef ELF_TYPE
fine _scanf scanf
fine _printf printf
fine _getchar getchar
fine _putchar putchar
fine _fputs fputs
%endif
%ifdef OBJ_TYPE
segment .data public align=4 class=data use32
%else
segment .data
%endif
int_format db "%i", 0
string_format db "%s", 0
reg_format db "Register Dump # %d", NL
db "EAX = %.8X EBX = %.8X ECX = %.8X EDX = %.8X", NL
db "ESI = %.8X EDI = %.8X EBP = %.8X ESP = %.8X", NL
db "EIP = %.8X FLAGS = %.4X %s %s %s %s %s %s %s", NL
db 0
carry_flag db "CF", 0
zero_flag db "ZF", 0
sign_flag db "SF", 0
parity_flag db "PF", 0
overflow_flag db "OF", 0
dir_flag db "DF", 0
aux_carry_flag db "AF", 0
unset_flag db " ", 0
mem_format1 db "Memory Dump # %d Address = %.8X", NL, 0
mem_format2 db "%.8X ", 0
mem_format3 db "%.2X ", 0
stack_format db "Stack Dump # %d", NL
db "EBP = %.8X ESP = %.8X", NL, 0
stack_line_format db "%+4d %.8X %.8X", NL, 0
math_format1 db "Math Coprocessor Dump # %d Control Word = %.4X"
db " Status Word = %.4X", NL, 0
valid_st_format db "ST%d: %.10g", NL, 0
invalid_st_format db "ST%d: Invalid ST", NL, 0
empty_st_format db "ST%d: Empty", NL, 0
;
; code is put in the _TEXT segment
;
%ifdef OBJ_TYPE
segment text public align=1 class=code use32
%else
segment .text
%endif
global read_int, print_int, print_string, read_char
global print_char, print_nl, sub_dump_regs, sub_dump_mem
global sub_dump_math, sub_dump_stack
extern _scanf, _printf, _getchar, _putchar, _fputs
read_int:
enter 4,0
pusha
pushf
lea eax, [ebp-4]
push eax
push dword int_format
call _scanf
pop ecx
pop ecx
popf
popa
mov eax, [ebp-4]
leave
ret
print_int:
enter 0,0
pusha
pushf
push eax
push dword int_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
print_string:
enter 0,0
pusha
pushf
push eax
push dword string_format
call _printf
pop ecx
pop ecx
popf
popa
leave
ret
read_char:
enter 4,0
pusha
pushf
call _getchar
mov [ebp-4], eax
popf
popa
mov eax, [ebp-4]
leave
ret
print_char:
enter 0,0
pusha
pushf
push eax
call _putchar
pop ecx
popf
popa
leave
ret
print_nl:
enter 0,0
pusha
pushf
push dword 10 ; 10 == ASCII code for \n
call _putchar
pop ecx
popf
popa
leave
ret
sub_dump_regs:
enter 4,0
pusha
pushf
mov eax, [esp] ; read FLAGS back off stack
mov [ebp-4], eax ; save flags
;
; show which FLAGS are set
;
test eax, CF_MASK
jz cf_off
mov eax, carry_flag
jmp short push_cf
cf_off:
mov eax, unset_flag
push_cf:
push eax
test dword [ebp-4], PF_MASK
jz pf_off
mov eax, parity_flag
jmp short push_pf
pf_off:
mov eax, unset_flag
push_pf:
push eax
test dword [ebp-4], AF_MASK
jz af_off
mov eax, aux_carry_flag
jmp short push_af
af_off:
mov eax, unset_flag
push_af:
push eax
test dword [ebp-4], ZF_MASK
jz zf_off
mov eax, zero_flag
jmp short push_zf
zf_off:
mov eax, unset_flag
push_zf:
push eax
test dword [ebp-4], SF_MASK
jz sf_off
mov eax, sign_flag
jmp short push_sf
sf_off:
mov eax, unset_flag
push_sf:
push eax
test dword [ebp-4], DF_MASK
jz df_off
mov eax, dir_flag
jmp short push_df
df_off:
mov eax, unset_flag
push_df:
push eax
test dword [ebp-4], OF_MASK
jz of_off
mov eax, overflow_flag
jmp short push_of
of_off:
mov eax, unset_flag
push_of:
push eax
push dword [ebp-4] ; FLAGS
mov eax, [ebp+4]
sub eax, 10 ; EIP on stack is 10 bytes ahead of orig
push eax ; EIP
lea eax, [ebp+12]
push eax ; original ESP
push dword [ebp] ; original EBP
push edi
push esi
push edx
push ecx
push ebx
push dword [ebp-8] ; original EAX
push dword [ebp+8] ; # of dump
push dword reg_format
call _printf
add esp, 76
popf
popa
leave
ret 4
sub_dump_stack:
enter 0,0
pusha
pushf
lea eax, [ebp+20]
push eax ; original ESP
push dword [ebp] ; original EBP
push dword [ebp+8] ; # of dump
push dword stack_format
call _printf
add esp, 16
mov ebx, [ebp] ; ebx = original ebp
mov eax, [ebp+16] ; eax = # dwords above ebp
shl eax, 2 ; eax *= 4
add ebx, eax ; ebx = & highest dword in stack to display
mov edx, [ebp+16]
mov ecx, edx
add ecx, [ebp+12]
inc ecx ; ecx = # of dwords to display
stack_line_loop:
push edx
push ecx ; save ecx & edx
push dword [ebx] ; value on stack
push ebx ; address of value on stack
mov eax, edx
sal eax, 2 ; eax = 4*edx
push eax ; offset from ebp
push dword stack_line_format
call _printf
add esp, 16
pop ecx
pop edx
sub ebx, 4
dec edx
loop stack_line_loop
popf
popa
leave
ret 12
sub_dump_mem:
enter 0,0
pusha
pushf
push dword [ebp+12]
push dword [ebp+16]
push dword mem_format1
call _printf
add esp, 12
mov esi, [ebp+12] ; address
and esi, 0FFFFFFF0h ; move to start of paragraph
mov ecx, [ebp+8]
inc ecx
mem_outer_loop:
push ecx
push esi
push dword mem_format2
call _printf
add esp, 8
xor ebx, ebx
mem_hex_loop:
xor eax, eax
mov al, [esi + ebx]
push eax
push dword mem_format3
call _printf
add esp, 8
inc ebx
cmp ebx, 16
jl mem_hex_loop
mov eax, '"'
call print_char
xor ebx, ebx
mem_char_loop:
xor eax, eax
mov al, [esi+ebx]
cmp al, 32
jl non_printable
cmp al, 126
jg non_printable
jmp short mem_char_loop_continue
non_printable:
mov eax, '?'
mem_char_loop_continue:
call print_char
inc ebx
cmp ebx, 16
jl mem_char_loop
mov eax, '"'
call print_char
call print_nl
add esi, 16
pop ecx
loop mem_outer_loop
popf
popa
leave
ret 12
; function sub_dump_math
; prints out state of math coprocessor without modifying the coprocessor
; or regular processor state
; Parameters:
; dump number - dword at [ebp+8]
; Local variables:
; ebp-108 start of fsave buffer
; ebp-116 temp double
; Notes: This procedure uses the Pascal convention.
; fsave buffer structure:
; ebp-108 control word
; ebp-104 status word
; ebp-100 tag word
; ebp-80 ST0
; ebp-70 ST1
; ebp-60 ST2 ...
; ebp-10 ST7
;
sub_dump_math:
enter 116,0
pusha
pushf
fsave [ebp-108] ; save coprocessor state to memory
mov eax, [ebp-104] ; status word
and eax, 0FFFFh
push eax
mov eax, [ebp-108] ; control word
and eax, 0FFFFh
push eax
push dword [ebp+8]
push dword math_format1
call _printf
add esp, 16
;
; rotate tag word so that tags in same order as numbers are
; in the stack
;
mov cx, [ebp-104] ; ax = status word
shr cx, 11
and cx, 7 ; cl = physical state of number on stack top
mov bx, [ebp-100] ; bx = tag word
shl cl,1 ; cl *= 2
ror bx, cl ; move top of stack tag to lowest bits
mov edi, 0 ; edi = stack number of number
lea esi, [ebp-80] ; esi = address of ST0
mov ecx, 8 ; ecx = loop counter
tag_loop:
push ecx
mov ax, 3
and ax, bx ; ax = current tag
or ax, ax ; 00 -> valid number
je valid_st
cmp ax, 1 ; 01 -> zero
je zero_st
cmp ax, 2 ; 10 -> invalid number
je invalid_st
push edi ; 11 -> empty
push dword empty_st_format
call _printf
add esp, 8
jmp short cont_tag_loop
zero_st:
fldz
jmp short print_real
valid_st:
fld tword [esi]
print_real:
fstp qword [ebp-116]
push dword [ebp-112]
push dword [ebp-116]
push edi
push dword valid_st_format
call _printf
add esp, 16
jmp short cont_tag_loop
invalid_st:
push edi
push dword invalid_st_format
call _printf
add esp, 8
cont_tag_loop:
ror bx, 2 ; mov next tag into lowest bits
inc edi
add esi, 10 ; mov to next number on stack
pop ecx
loop tag_loop
frstor [ebp-108] ; restore coprocessor state
popf
popa
leave
ret 4
4.asm_io.inc
extern read_int, print_int, print_string
extern read_char, print_char, print_nl
extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack
%macro dump_regs 1
push dword %1
call sub_dump_regs
%endmacro
;
; usage: dump_mem label, start-address, # paragraphs
%macro dump_mem 3
push dword %1
push dword %2
push dword %3
call sub_dump_mem
%endmacro
%macro dump_math 1
push dword %1
call sub_dump_math
%endmacro
%macro dump_stack 3
push dword %3
push dword %2
push dword %1
call sub_dump_stack
%endmacro
이상입니다.
댓글 0