Paul Carter 꺼 공부하고 있습니다.

저희 컴퓨터는 윈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


이상입니다.