Page 1 of 1

code not outputting data string

Posted: Tue Aug 12, 2003 3:06 pm
by Stephen
Here's the deal. I have an executable program that consists of 3 object files put together. 2 of the object files are compiled assembly code and 1 is a C source code file. They all compile together fine with gcc, but when I execute the program from a MS-DOS prompt is where the trouble is. Based on the main assembler code file (test1.asm), I move a value into the eax register, and then call the print_string function, which in turn calls the C function printf. At this point, I should see that value display on the screen, but I don't. Can anyone see anything obvoius in this code which would be causing this problem?

TEST1.ASM
*****************************************
; file: test1.asm
; First assembly program testing the ability
; to store data in the EAX register and print
; it to the screen.
;
; Syntax to create executable using DJGPP:
; nasm -f coff test1.asm
; gcc -o test1 test1.o driver.c asm_io.o

%include "e:\djgpp\asm_io.inc"

; initialized data should be placed under
; the .data segment
segment .data
output1 db "Hello World ", 0 ;space after string = null terminator
segment .bss

segment .text
global _asm_main
_asm_main:
enter 0,0
pusha

; begin program code
mov eax, output1 ; prepare variable for output
call print_string ; invoke asm proc that calls C
; end program code

; all below information required
popa
mov eax,0 ; return back to C
leave
ret
*****************************************

print_string function in asm_io.asm
*****************************************
print_string:
   enter   0,0
   pusha
   pushf

   push   eax
   push dword string_format
   call   _printf
   pop   ecx
   pop   ecx

   popf
   popa
   leave
   ret
*****************************************

DRIVER.C
*****************************************
int asm_main(void);

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

Re:code not outputting data string

Posted: Tue Aug 12, 2003 5:42 pm
by Curufir

Code: Select all

push    dword string_format
Am I missing something, or have you not actually set string_format to be anything?

This is the only place I see it in your code.

Mind you, nasm should moan about it being used without being set first, so I don't see this as being the main problem seeing as you say it compiles ok.

Re:code not outputting data string

Posted: Thu Aug 14, 2003 4:19 am
by Stephen
The asm_io.asm file contains the string_format declaration. But if that's all that seems to be the problem, then can anyone else think of any platform specific issues I might be having here?

Re:code not outputting data string

Posted: Thu Aug 14, 2003 5:29 am
by Pype.Clicker
what is obvious to me is that
- you might prefer using pushad/popad instead of pusha/popa while some version of nasm have been encoding "pusha" as 16-bits-overriden, iirc (or was it just for iret. dunno...)

- do you have some constant characters in your "format string" that you see or is it just "%s" ? -- just to make sure things works on a simpler environment...

- do you have the evidence the strings and the code get included in your kernel ?

Re:code not outputting data string

Posted: Thu Aug 14, 2003 10:15 am
by Curufir
Ok, my C is rusty, but isn't the printf declaration something like:

Code: Select all

extern int printf(const char *, ...);
I only point this out because string_format must be a zero terminated string as well. Without that 0 the printf function will wander off into the wilderness when it tries to read the format string, probably breaking itself in the process and not performing the print.

Far as I can see you push the two memory references in the right order, how about testing the return value of printf (ie EAX) (Assuming it does actually return). Should be a 1 for correct operation I think.

Is "extern _printf" declared in asm_io.asm as well?

Re:code not outputting data string

Posted: Sat Aug 16, 2003 2:32 pm
by Stephen
Here is the asm_io.asm file - the piece of code I did not place on here. This way, everyone can see for themselves. This is the first portion of the file:

;
; 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

%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
%define _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

Re:code not outputting data string

Posted: Sat Aug 16, 2003 2:33 pm
by Stephen
And this is the second part of the file:

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

Re:code not outputting data string

Posted: Mon Aug 18, 2003 7:50 pm
by bakersoft_corp
Nevermind, I figured it out. Dumb mistake.