Recent Posts

Pages: 1 ... 7 8 [9] 10
81
Programming with NASM / So where is it safe to write to RAM in a DOS program?
« Last post by ben321 on February 15, 2023, 05:48:49 AM »
What regions of RAM are safe to write to in DOS program? I know some are memory mapped hardware like VRAM being located at 0xA0000 for VGA. I know other parts are DOS and those shouldn't be overwritten if you want to avoid overwriting DOS code (especially the DOS interrupt code). And yet other parts map to ROM. So I need to know what regions of memory are actually safe to use as a working space in a program. Note I'm talking about a DOS COM program, not an EXE, so DOS isn't doing much memory management for it (meaning I need to know myself what parts of memory are safe to use as a working space for my program).
82
Programming with NASM / Re: Why does DOS Box Debugger show this as illegal?
« Last post by ben321 on February 15, 2023, 05:46:35 AM »
Can somebody delete this last post I made in this thread. I can't delete my own post here. I meant to start a new thread but accidentally commented in this one.
83
Programming with NASM / Re: Need Information.
« Last post by Frank Kotler on February 14, 2023, 10:33:53 PM »
Yes. Thank you!

Best,
Frank

84
Here's a good reference for legacy I/O address space (in the PDF attached). And take a look at the legacy PIC (Programmable Interrupt Controller) and KBC (KeyBoard Controller) -- you can find about them in OSDev site.

And this question is VERY... VERY... basic. You could make a better effort to find this info, that it's NOT hard to find.
85
Programming with NASM / Re: Need Information.
« Last post by fredericopissarra on February 14, 2023, 12:25:47 PM »
Hehee... Me and Frank wrote almost the same thing almost the same time... ;)
86
Programming with NASM / Re: Why does DOS Box Debugger show this as illegal?
« Last post by alCoPaUL on February 13, 2023, 11:24:58 PM »
DOSBox-X behaves exactly like legacy DOS. you can get TASM 5 (winworldpc) and install everything and from that, youll get DOS/W32 GUI debuggers. then if those don't meet your needs, go download SoftICE (an abandonware at the moment).
87
Programming with NASM / Re: Need Information.
« Last post by fredericopissarra on February 13, 2023, 09:29:45 PM »
One of the things I notice is that at the end of a sub routine there are typicially two types of returns, both with the mnemonic RET, but with different op-codes.

There are, actually, 4 different opcodes for RET. 0xC3 is for NEAR return, 0xCB is for FAR return (retf), 0xC2 is the same as RET near, but add an immediate value to (R|E)SP. And there is 0xCA, which is the same as a far return, but adds the immediate value as 0xC2 does.

Quote
The two op-codes I've seen are C2 and C3. C3 takes no parameter. C2 takes a two byte "word" parameter. What I can't figure out is what you are supposed to pass to that parameter.

Certain languages, for example, PASCAL, passes arguments through the stack and expect the called function to do the cleanup. Others, like C, do the cleanup in the caller. Let's say we have, in PASCAL:
Code: [Select]
function F( x : Integer ) : Integer;
begin
  F := 2 * x;
end;
The pascal compiler will, probably, create something like:
Code: [Select]
F:
  mov eax,[esp+4]
  add eax,eax
  ret 4   ; dispose of the argument on the stack.
But a C compiler with a function like this:
Code: [Select]
int f( int x ) { return x + x; }Probably will create:
Code: [Select]
_f:
  mov eax,[esp+4]
  add eax,eax
  ret     ; DON'T dispose of the argument on the stack
          ; leting the caller to do this
When f() is called, the C compiler does:
Code: [Select]
; Example: y = f(2); -- supose y is ECX.
  push 2   ; pushes the 2 argument to the stack
  call _f
  add  esp,4 ; clears the stack
  mov  ecx,eax

Quote
I also notice that just prior to the RET, there is usually a LEAVE command.

LEAVE is an old instruction and should not be used anymore. Essentially it does a pair of instructions at once: `mov esp,ebp/pop ebp`, but this isn't necessary anymore... Not even the usage of EBP as a substitute for using ESP, because, since 386 ESP can be used in an effective address (that address between [ and ]). Until 286 only BX,BP,SI and DI could be used. 386 changed this.

Using NASM you can use structures to make sure the arguments are in their proper positions without having to calculate the relative stack position yourself... Let's take a look at f(), above... Before you call f() the 2 is pushed to the stack, so ESP points to the position where this 2 is... The CALL instruction pushes contents of EIP, so RET will know where to return to, then CALL jumps to f. Your stack will be like this after the CALL:
Code: [Select]
  ESP+4 -> 2
  ESP   -> EIP
Notice that we can use a structure like this:
Code: [Select]
struc fstk
     resd  1    ; offset 0, where ESP points to... the return address.
.x:  resd  1    ; offset 4, where out argument is.
endstruc

_f:
  mov eax,[esp + fstk.x]   ; fstk.x is the offset 4
  add eax,eax
  ret

No need to use `EBP` instead of `ESP`.
88
Programming with NASM / Re: Need Information.
« Last post by Frank Kotler on February 13, 2023, 09:24:48 PM »
To get an idea of how programs look in assembly language, I've written a few simple programs in VB6 and then disassembled them with OllyDbg. One of the things I notice is that at the end of a sub routine there are typicially two types of returns, both with the mnemonic RET, but with different op-codes. The two op-codes I've seen are C2 and C3. C3 takes no parameter. C2 takes a two byte "word" parameter. What I can't figure out is what you are supposed to pass to that parameter. Is it some relative memory location? Is it supposed to be a value that gets put on some register, or somewhere in the stack, for later use by the program? And in what situation would I most often use a C2 return, versus when should I use a C3 return?
Hi Francis,
Good question(s)!
It has to do with "calling conventions". You are looking at 32 bit code, where parameters are pushed on the stack. In a "caller cleans up" convention (C, for example) you use a plain "RET". In   a "callee cleans up" (Windows APIs, for example) you use "RET n" where "n" is the number of bytes (not number of parameters) to be removed from the stack after the return, freeing the caller from having to do it.

Quote
I also notice that just prior to the RET, there is usually a LEAVE command. This has the op-code C9. According to this documentation http://ref.x86asm.net/coder32.html a C9 is a "High Level Procedure Exit". What exactly does this mean? In what situations is a LEAVE needed?
It means what it says. It is a "high level" instruction equivalent to:
Code: [Select]
mov esp, ebp ; restore esp to the value it had before "local variables" were allocated
pop ebp : restore caller's ebp saved at beginning of function
Calling conventions require that certain registers be preserved (to the caller's values) across the function. ebx, esi, edi, and ebp. esp, the stack pointer, must be back where it was, because the location we RET to is popped off the stack. If this isn't "right" we will surely crash!
Quote
In cases where LEAVE is not used, the RET is always preceded by a POP EBP. But I can't figure out, in what situations should a POP EBP be used instead of a LEAVE? I also notice that at the start of any subroutine, without fail, and regardless of what commands are used near the end of the routine, the first command is always PUSH EBP. Why is that used?

ebp is one of the caller's registers which must always be preserved.

There is an "ENTER 0 , 0" instruction which more or less "matches" the "LEAVE" instruction. The first 0 is the 'depth" of how many functions have called this one. The Pascal language allows functions to access the caller's local variables. This value is required to do that calculation. The second 0 is the number of bytes to be subtracted from esp to allocate space for "local" or "automatic" variables. "enter" is slower than doing it "by hand", so it isn't often used. "leave" is a fast as doing it "by hand" so it often is used. Neither of them is "necessary".

To take it from the top:
Code: [Select]
push parameter1
push parameter2
; etc. ?
call afunction; a caller cleans up function
add esp, 8 ; remove parameters from stack
;...
afunction:
push ebp ; save caller's reg
mov ebp, esp ; if local variables
sub esp, 8 ; enough space for two local variables
push ebx
push esi
push edi ; if we alter them

; some code
mov eax, [ebp + 4] ; use parameter 1... etc.

pop edi
pop esi
pop ebp ; if we altered 'em and had to save 'em

mov esp, ebp ; remove local variables, if any
pop ebp ; restore caller's ebp
; or "leave" will replace these two instructions
ret

or if it's a callee cleans up function

Code: [Select]
push paraneter1
push parameter2
call bfunction
; the "ret 8" has removed parameters
; ...
bfunction:
push ebp ; save caller's reg
mov ebp, esp
sub esp, 8 ; space for two local variables
; suppose we don't alter ebx, esi, or edi
;some code

mov esp, ebp
pop ebp ; restore caller's reg
; or "leave"
ret 8 ; return and clean up stack

It may be worth noting that in 16 bit code, [sp] was not valid, so [bp] had to be used. In 32 bit code [esp] is valid...
Well... these are good questions, Francis. If I haven't explained fully, or if I screwed up, feel free to ask more!

Best,
Frank

89
Programming with NASM / Re: Why does DOS Box Debugger show this as illegal?
« Last post by ben321 on February 13, 2023, 09:12:23 PM »
get DOSBox-X for Classic Real Mode (MS-DOS, etc) emulation.

DOSBox is kinda "customized", but not that it restricts some stuffs but it allows some stuffs to function/go through.

like DOSBox-X is still a subset of DOSBox based on what i said.

I need a debugger to see each instruction getting executed and its effect on the system's state (such as switching to real mode) to make sure that my code is working as intended. The debugger version of DosBox has this. DosBox-X doesn't have any debugger version as far as I've heard. So while I can see the output via the screen window (just like in regular DosBox), I can't be sure of the internal state of the system, so bugs may exist in my code that don't present themselves normally, but when I write more code it might impact the execution of that additional code. So it's helpful to see the code as it gets executed in a debugger.
90
Programming with NASM / Re: Need Information.
« Last post by alCoPaUL on February 13, 2023, 08:57:42 PM »
youll get pcode functions from the vb6 runtime if you base at vb6 to learn assembly.

try c programming coz it's sooo close to assembly opcodes when decompiling/disassembling them.

from there, it will funnel to the things that you want to do.

you wanna be a systems/kernel driver developer?
you wanna be a library .dll developer or some API stuff?
or you just wanna play around some concepts and express it to code (no money gotten from here)?

or some haxxor stuff?

your choice.

now, let's say your computer hardware with software (CPU Tower + OS) is traversing space-time and you click ninja.exe,

ninja can enter the space-time with respect to your computer via

sub rsp, 28h

ninja is here

add rsp, 28h

or

push rbx

ninja is here

pop rbx

or

enter 0,0

ninja is here

leave

or

org 100

ninja is here

int 20

so, that's basically what happens when you view it on some other pov.

and if the ninja is like a matrioshka doll, she can port 6 more ninjas inside the bounds of her presence inside the space-time of the computer..

or if she can do it to the maximum numbers, the ninja operated like a port that can accommodate infinity - 1.
Pages: 1 ... 7 8 [9] 10