Frage

Ich versuche, Montage Dr. Paul Carter pcasm Buch mit lernen: http: //www.drpaulcarter. com / pcasm /

Verwendung von Linux-Quellen

Der Autor verpackt nicht Mac OS X Proben, dann habe ich begonnen. Hier ist die erste Probe, die seine Bibliothek asm_io verwendet.

Ich bin immer Segmentation Fault, wenn es ausgeführt wird. Warum? Was muss geändert werden in Mac?

Ich denke, wenn Sie asm wissen, vielleicht können Sie mir sagen, was los ist.

Hier ist die Quellen.

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
; To assemble for Watcom
;   nasm -f obj -d OBJ_TYPE -d WATCOM asm_io.asm
; IMPORTANT NOTES FOR WATCOM
;   The Watcom compiler's C library does not use the
;   standard C calling convention. For example, the
;   putchar() function gets its argument from the
;   the value of EAX, not the stack.


%define NL 10
%define CF_MASK 00000001h
%define PF_MASK 00000004h
%define AF_MASK 00000010h
%define ZF_MASK 00000040h
%define SF_MASK 00000080h
%define DF_MASK 00000400h
%define OF_MASK 00000800h


;
; Linux C doesn't put underscores on labels
;
%ifdef ELF_TYPE
  %define _scanf   scanf
  %define _printf  printf
  %define _getchar getchar
  %define _putchar putchar
%endif

;
; Watcom puts underscores at end of label
;
%ifdef WATCOM
  %define _scanf   scanf_
  %define _printf  printf_
  %define _getchar getchar_
  %define _putchar putchar_
%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

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

%ifndef WATCOM
 push eax
%endif
 call _putchar
%ifndef WATCOM
 pop ecx
%endif

 popf
 popa
 leave
 ret


print_nl:
 enter 0,0
 pusha
 pushf

%ifdef WATCOM
 mov eax, 10  ; WATCOM doesn't use the stack here
%else
 push dword 10 ; 10 == ASCII code for \n
%endif
 call _putchar
%ifndef WATCOM
 pop ecx
%endif
 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

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

first.asm

;
; file: first.asm
; First assembly program. This program asks for two integers as
; input and prints out their sum.
;
; To create executable:
; Using djgpp:
; nasm -f coff first.asm
; gcc -o first first.o driver.c asm_io.o
;
; Using Linux and gcc:
; nasm -f elf first.asm
; gcc -o first first.o driver.c asm_io.o
;
; Using Borland C/C++
; nasm -f obj first.asm
; bcc32 first.obj driver.c asm_io.obj
;
; Using MS C/C++
; nasm -f win32 first.asm
; cl first.obj driver.c asm_io.obj
;
; Using Open Watcom
; nasm -f obj first.asm
; wcl386 first.obj driver.c asm_io.obj

%include "asm_io.inc"
;
; initialized data is put in the .data segment
;
segment .data
;
; These labels refer to strings used for output
;
prompt1 db    "Enter a number: ", 0       ; don't forget nul terminator
prompt2 db    "Enter another number: ", 0
outmsg1 db    "You entered ", 0
outmsg2 db    " and ", 0
outmsg3 db    ", the sum of these is ", 0


;
; uninitialized data is put in the .bss segment
;
segment .bss
;
; These labels refer to double words used to store the inputs
;
input1  resd 1
input2  resd 1



;
; code is put in the .text segment
;
segment .text
        global  _asm_main
_asm_main:
        enter   0,0               ; setup routine
        pusha

        mov     eax, prompt1      ; print out prompt
        call    print_string

        call    read_int          ; read integer
        mov     [input1], eax     ; store into input1

        mov     eax, prompt2      ; print out prompt
        call    print_string

        call    read_int          ; read integer
        mov     [input2], eax     ; store into input2

        mov     eax, [input1]     ; eax = dword at input1
        add     eax, [input2]     ; eax += dword at input2
        mov     ebx, eax          ; ebx = eax
        dump_regs 1               ; dump out register values
        dump_mem 2, outmsg1, 1    ; dump out memory
;
; next print out result message as series of steps
;
        mov     eax, outmsg1
        call    print_string      ; print out first message
        mov     eax, [input1]     
        call    print_int         ; print out input1
        mov     eax, outmsg2
        call    print_string      ; print out second message
        mov     eax, [input2]
        call    print_int         ; print out input2
        mov     eax, outmsg3
        call    print_string      ; print out third message
        mov     eax, ebx
        call    print_int         ; print out sum (ebx)
        call    print_nl          ; print new-line

        popa
        mov     eax, 0            ; return back to C
        leave                     
        ret

drive.c:

#include "cdecl.h"

int PRE_CDECL asm_main( void ) POST_CDECL;

int main()
{
  int ret_status;
  ret_status = asm_main();
  return ret_status;
}

ich es jetzt kompilieren mit:

nasm -f macho first.asm

nasm -f macho asm_io.asm

gcc first.o asm_io.o driver.c -o erste -arch i386

Dann laufen: ./first

Segmentation fault

Es geschieht nur, wenn ich asm_io lib bin mit.

Danke,

Daniel Koch

War es hilfreich?

Lösung

Sie scheinen 32-Bit-Assembler-Code hier zu verwenden. Ein großer Unterschied zwischen 32-Bit Mac OS X und 32-Bit-Windows oder Linux ist, dass Mac den Stapel benötigt 16 Byte ausgerichtet sein, wenn Sie eine Funktion CALL. Mit anderen Worten, an der Stelle in Ihrem Code, wo Sie eine CALL Anweisung haben, ist es erforderlich, dass ESP = #######0h.

Das folgende kann interessant sein, lautet:

http://blogs.embarcadero.com/eboling/2009/05 / 20/5607

www.agner.org/optimize/calling_conventions.pdf

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top