NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: KrukersRadek on January 13, 2012, 03:54:14 PM

Title: NASM second program, but for win32
Post by: KrukersRadek on January 13, 2012, 03:54:14 PM
I have got a code:

Driver.c
Code: [Select]
#include "cdecl.h"
#include <stdio.h>

int PRE_CDECL asm_main( void ) POST_CDECL;

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

a.asm
Code: [Select]
%include "asm_io.inc"
extern _printf

segment data
hello  db      'hello, world', 13, 10, '$'
myint dd 1234
mystring db 'This number -> %d <- should be 1234',10,0



segment code
global _asm_main
_asm_main:
enter 12,0
pusha

mov eax,1234
call print_int

popa
leave
ret
      
And I have got files in my directory:
asm_io.asm
asm_io.inc


my compilation:
nasm -f coff asm_io.asm
nasm -f coff a.asm
gcc -c driver.c
gcc -o a.exe a.o driver.o asm_io.o

Program display register eax on standard output (display).

Compilation is successful, but when I start a.exe appear a error similar to memory overflow.
I don't want to show window of error because it is written in polish.
What does it mean?
can somebody try to compile the same way like me?

Please help!
Title: Re: NASM second program, but for win32
Post by: Rob Neff on January 13, 2012, 04:28:15 PM
You are most likely suffering from cdecl stack issues.
Post your asm_io files so we can take a look at them too in order to better help you.
If they're large files then attach the file to the post instead.
Title: Re: NASM second program, but for win32
Post by: KrukersRadek on January 13, 2012, 04:42:14 PM
ok.

asm_io.asm
Code: [Select]
;
; 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
Code: [Select]
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
Title: Re: NASM second program, but for win32
Post by: Frank Kotler on January 13, 2012, 08:20:19 PM
Heh! "Kotler" used to be "Kotlewski" (back before my dad was born - claimed it was German, but it sure sounds Polish to me!), but I don't speak a word of Polish, so thanks for struggling with English!

What we have here appears to be Dr. Paul Carter's tutorial, which uses C library functions to work with multiple OSes. The interface to C is hidden away in asm_io.asm, which "should" take care of any stack issues. I can see you're using gcc... but is it DJGPP's gcc or MinGW/Cygwin gcc? Nasm's "-f coff" output format would be correct for DJGPP. Microsoft uses a slightly different version of COFF (Common Object File Format), which Nasm knows as "-f win32". I think "-f win32" would be correct for MinGW/Cygwin gcc. Try assembling a.asm and asm_io.asm as "-f win32", and see if that fixes the problem. (easy to try, anyway)

Dr. Carter's instructions suggest defining "COFF_TYPE" on Nasm's command line with "-d COFF_TYPE". You don't do this, but I don't think that's the problem. That removes the leading underscore from "_main", "_prinf", etc. for Linux, and makes it a trailing underscore for Watcom. I think if that were the problem, you'd see "unresolved external" from the linker.

I would suggest you use the "standard" names for sections/segments - "segment .data" and "segment .text" (and segment .bss if you use it). I'm not sure that really makes any difference, but it won't hurt to use names Nasm "knows". (see the Friendly Manual for others) (these are case sensitive! ".TEXT" won't work)

See if "-f win32" helps, first. If not, you may need to translate that Polish error message for us. :)

Best,
Frank

Title: Re: NASM second program, but for win32
Post by: KrukersRadek on January 13, 2012, 11:11:52 PM
Franku Kotlewski jeste? najlepszy!  ----> it means "Frank Kotler! You are the best!".

I do thank you. I had gcc version not for DJGPP and therefore my program didn't execute.

You suggested me "-f win32". I try but it didn't working good.
On polish forums anybody helps me.

I like programing in assembler. I still programing my program for education English language.
It will be big database with polish and english words. And many clever algorithms for exams.
It isn't finished, so I can't show you this program.

 But I programed graphic editor for MS-DOS (16bit program) (4 years ago)
 and I can show you my simply game also for MS-DOS. (1 year ago)
So if you want to see it you download it form link below:

http://www.sendspace.pl/file/f3e8198293aa3035139e23c     bitmap editor (TBF13H)
http://www.sendspace.pl/file/1a9b27c56a5019f38152e20     my simply game

Graphic for this game was made in TBF13H.

You remember! that it can execute only on MS-DOS platform or DosBox.
Dowidzenia ----> it means "Good bye"
And thanks! again time.