But when I started out, optimizations and dynamic complexity really confused me.
Static memory size was just something I copied from the original code, keeping it simple.
After optimizing later on I was really confused that the addresses were jumping, due to it being dynamic and me changing the code when programming.
Of course that had everything to do with me:
not using the code segments from the child process
I am doing the similar loader as what Akuma did
However, my problem is that the executable I am working will sometime go to protected mode and
it will use dos extender to write the memory into address greater than 1Mb
I built the loader with nasm and running in real mode (16bit) add modified the interrupt 21h to add my own code (i.e. changed the int vector of 21)
I can see from dosbox debugger that my code is running, but it is in real mode, all the memory content I want to check from the executable is gone (as it is marked in protected mode)
Please can you shed some light how can i access the memory in real mode? Or i need to switch to protected mode? (it seems very complicated for newbie like me)
p.s. the memory address I want to check is at 0x0044a30c
DosIssue.png
1BITS 16 2;memsize equ 220h ;memory size 220h/544 bytes 3;org 0x7c00 ;this is a .com file 4org 0x100 5section .data 6message db 'my loader.',0Dh,0Ah, 7 db '2021',0Dh,0Ah,'$' 8filename db 'SSDFLASH.EXE',0 ;filename to load 9params times 22 db 000h ;parameter block is 22 bytes 10 ; see int21h=4b documentation 11HEX_OUT db '00000000',0dh,0ah, 0 12 13section .text 14;------------------------------------------------------------------------------ 15start: 16;------------------------------------------------------------------------------ 17;we reposition the stackpointer memsize, 18; set no. pages in bx by dividing: memsize / pagesize (16 bytes) = no. pages 19; then we resize our memory usage to the number of pages 20 21 mov sp, end_app 22 mov bx,sp 23 shr bx,4 24; mov sp,memsize ;point stackpointer 25 ; to end of memory 26; mov bx,memsize/010h ;no. pages = memsize / 16 27 mov ah,04Ah ;resize memory 28 int 21h ;commit 29 30 mov dx,message ;point to message 31 mov ah,009h ;write string to stdout 32 int 21h ;commit 33 34;------------------------------------------------------------------------------ 35;keystroke function uses a lot of stack space and could overwrite the end 36; of your program in memory if memsize is set too small 37 38 ; mov ah,000h ;keyboard - get keystroke 39 ; int 16h ;commit 40 41;------------------------------------------------------------------------------ 42;the interrupt vector table contains addresses and we retrieve the address 43; from interrupt 16h and save it into the jump address oldint 44; do not forget to restore es, because we need it later 45 46 mov ah,035h ;get interrupt vector 47 mov al,21h ;for interrupt 16h 48 int 21h ;commit 49 ;retuns es:bx=segment:offset 50 mov word [oldint+1],bx ;write offset to oldint 51 mov word [oldint+3],es ;write segment to oldint 52 push cs ;copy cs 53 pop es ;into es (restores es) 54 55 mov ah,025h ;set new interrupt vector 56 mov al,21h ;for interrupt 016h 57 mov dx,newint ;ds:dx = new address 58 int 21h ;commit 59 60;------------------------------------------------------------------------------
…Show last 185 lines
61;we set the filename (ds:dx) and parameters (es:bx) and then copy 62; our own cs segment into the parameter block 63 64 mov dx,filename ;filename to load 65 mov bx,params ;parameter block (es:bx) 66 mov word [bx+00],cs ;code segment 67 mov word [bx+02],080h ;command tail offset 68 mov word [bx+04],cs ;code segment 69 mov word [bx+06],05Ch ;first FCB 70 mov word [bx+08],cs ;code segment 71 mov word [bx+10],06Ch ;second FCB 72 mov word [bx+12],cs ;code segment 73 mov ah,04Bh ;exec - load and/or execute 74 mov al,000h ;load and execute 75 int 21h ;commit 76 push ax ;save return code 77 78;------------------------------------------------------------------------------ 79;we restore the 16h interrupt (ds:dx) from the old address in oldint 80 81 mov ah,025h ;set new interrupt vector 82 mov al,21h ;for interrupt 016h 83 mov dx,word [oldint+1] ;copy offset from oldint 84 mov ds,word [oldint+3] ;copy segment from oldint 85 int 21h ;commit 86 push cs ;copy cs 87 pop ds ;into ds (restores ds) 88 89 pop ax ;restore exec return code 90 mov ah,04Ch ;exit to dos 91 int 21h 92 93;------------------------------------------------------------------------------ 94;this is our new interrupt 16h function we point to which jumps to the 95; old interrupt afterwards. all registers that change must be saved and 96; restored afterwards to allow normal execution of the old interrupt. 97; in our case its only the flags. 98 99newint: 100 101 pushf ;save flags 102 pusha 103 cmp ah, 03eh 104 jnz exit 105 106 mov edx, 0x0044a30c 107 cmp word [edx], 0ec89h 108 jnz exit 109 110 mov edx, ebp 111 ;mov edx, ebp 112 call print_hex 113 mov ax,0e20h ;point to message 114 115 int 10h 116 mov ax,0e48h ;point to message 117 118 int 10h 119 mov ax,0e65h ;point to message 120 121 int 10h 122 mov ax,0e6ch ;point to message 123 124 int 10h 125 mov ax,0e6ch ;point to message 126 127 int 10h 128 mov ax,0e6fh ;point to message 129 130 int 10h 131 mov ax,0e21h ;point to message 132 133 int 10h 134 mov ax,0e0dh ;point to message 135 136 int 10h 137 mov ax,0e0ah ;point to message 138 139 int 10h 140 mov ax, 0e0dh 141 int 10h 142 mov ax, 0e0ah 143 ;mov dl, 02h 144 int 10h 145 146exit: 147 popa 148 popf ;restore flags 149oldint: 150 jmp 0:0 ;jump to offset:segment 151 ; and set on runtime 152;------------------------------------------------------------------------------ 153 154print_hex: 155 ; push all registers onto the stack 156 pusha 157 158 ; use si to keep track of the current char in our template string mov si, HEX_OUT + 2 159 mov esi, HEX_OUT 160 161 ; start a counter of how many nibbles we've processed, stop at 4 162 mov cx, 0 163 164next_character: 165 ; increment the counter for each nibble 166 inc cx 167 168 ; isolate this nibble 169 mov ebx, edx 170 and ebx, 0xf0000000 171 shr ebx, 20 172 173 ; add 0x30 to get the ASCII digit value 174 add bh, 0x30 175 176 ; If our hex digit was > 9, it'll be > 0x39, so add 7 to get 177 ; ASCII letters 178 cmp bh, 0x39 179 jg add_7 180 181add_character_hex: 182 ; put the current nibble into our string template 183 mov [esi], bh 184 185 ; increment our template string's char position 186 inc esi 187 188 ; shift dx by 4 to start on the next nibble (to the right) 189 shl edx, 4 190 191 ; exit if we've processed all 4 nibbles, else process the next 192 ; nibble 193 cmp cx, 8 194 jnz next_character 195 and bh, 0 196 mov [esi], bh 197 jmp _done 198 199_done: 200 ; copy the current nibble's ASCII value to a char in our template 201 ; string 202 203 mov bx, HEX_OUT 204 205 ; print our template string 206 call print_string 207 208 ; pop all arguments 209 popa 210 211 ; return from subroutine 212 ret 213 214add_7: 215 ; add 7 to our current nibble's ASCII value, in order to get letters 216 add bh, 0x7 217 218 ; add the current nibble's ASCII 219 jmp add_character_hex 220 221print_string: 222 pusha 223 mov ah, 0xe 224 225print_character: 226 mov al, [bx] 227 inc bx 228 or al, al 229 jz print_done 230 int 0x10 231 jmp print_character 232 233print_done: 234 popa 235 ret 236 237 238 239 240 241section .bss 242alignb 16 243resw 256 244end_app: