code not outputting data string

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Stephen

code not outputting data string

Post 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;
}
*****************************************
Curufir

Re:code not outputting data string

Post 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.
Stephen

Re:code not outputting data string

Post 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?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:code not outputting data string

Post 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 ?
Curufir

Re:code not outputting data string

Post 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?
Stephen

Re:code not outputting data string

Post 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
Stephen

Re:code not outputting data string

Post 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
bakersoft_corp

Re:code not outputting data string

Post by bakersoft_corp »

Nevermind, I figured it out. Dumb mistake.
Post Reply