2021年4月24日星期六

String Corruption in my Number Printing Function for 16bit Real Mode DOS

I'm writing a program that will run in 16bit real-mode in DOS, compiling with GCC, and testing under DOSBox.

This is the linker script I am using to create the executable (coped from https://github.com/skeeto/dosdefender-ld31/blob/master/com.ld):

OUTPUT_FORMAT(binary)  SECTIONS  {      . = 0x0100;      .text :      {          *(.text);      }      .data :      {          *(.data);          *(.bss);          *(.rodata);      }      _heap = ALIGN(4);  }  

I can print strings terminated with a '$', but cannot with a 2 character string containing a digit and a '$'; I get a memory dump as you can see below:

DOSBox showing dumped memory

Here's my makefile, I pass flags to gcc minimize size, and not to link to a C runtime library.

CC      = gcc  DOS     = dosbox  CFLAGS  = -std=gnu99 -Wall -Wextra -Os -nostdlib -m32 -march=i386 \    -Wno-unused-function \    -ffreestanding -fomit-frame-pointer -fwrapv -fno-strict-aliasing \    -fno-leading-underscore -fno-pic -fno-stack-protector \    -Wl,--nmagic,-static,-Tcom.ld,--verbose=99      .PHONY : all clean test    all:      $(CC) -o bottles.com $(CFLAGS) main.c    clean :      $(RM) *.com    test : bottles.com      $(DOS) $^    %.com : %.c      $(CC) -o $@ $(CFLAGS) $<    

Here is 'main.c':

asm (".code16gcc\n"       "call  dosmain\n"       "mov   $0x4C,%ah\n"       "int   $0x21\n");    static void print(char *string)  {      asm volatile ("mov   $0x09, %%ah\n"                    "int   $0x21\n"      : /* no output */      : "d"(string)      : "ah");  }    static int _pow(int a, int b)  {      int x = a;      for (int i=1; i < b; i++) {          x = x * a;      }      return x;  }    static int getdigits(int val)  {      int d = 0;      int n = val;      while (n != 0) {          n /= 10;          d++;      }      return d;  }    static void putint(int val)  {      const int digits_num = getdigits(val);      const int base10_m = _pow(10, (digits_num - 1));      int r = val;      const char eof = '$';      char digit_s[2] = {0,eof};      for (int i = base10_m; i >= 10 ; i/=10) {          digit_s[0] = '0' + ( r - ( r % i ) ) / i ;          print(digit_s);          r -= ( r - ( r % i ));      }      digit_s[0] = '0' + r;      print(digit_s);  }    int dosmain(void)  {      print(1337);      return 0;  }    

What is causing the memory to be dumped as shown above?

https://stackoverflow.com/questions/67249216/string-corruption-in-my-number-printing-function-for-16bit-real-mode-dos April 25, 2021 at 10:29AM

没有评论:

发表评论