Welcome, Guest. Please login or register.
Did you miss your activation email?


Login with username, password and session length

News

Welcome to Yet Another Programming Community!

 
Pages: [1]   Go Down Print
Author Topic: Hyperspeed tutorial - DLLs in ASM  (Read 439 times)
Score_Under
Jr. Member
**

Karma: +2/-0
Offline Offline

Posts: 62


View Profile Email
« on: September 03, 2009, 01:10:28 PM »

This will be focused on writing DLLs in ASM using Flat Assember. To debug your DLL, or watch other programs and learn from them, then you will need OllyDbg. Get 1.10, not 2.0 beta.
I will try to keep it quick and simple, but if you don't understand something just say.

This assumes a prior knowledge of 32-bit Intel Syntax ASM.

First, we tell FASM what type of executable to build:
Code:
format PE GUI 4.0 DLL
It can even build Linux ELF when on Windows, so it's a pretty powerful tool Wink This directive tells it what format it is using, and what type of MZ/PE file to make (DLL in this case. It will also automatically append the correct extension. Omit the word "DLL" to make a normal EXE)

Code:
entry DllEntryPoint
Here we give the entry point, pretty much the main() function. Simple.

Code:
include 'win32a.inc'
This includes a few constants and common macros (like "import", "library", and "export"). You'll want this.

Next...
Code:
section '.text' code readable executable
We create our code section. Notice the attributes. You can specify: code, data, import, export, fixups, readable, writable, executable. I usually lump things into one section, but it's not recommended Tongue

Now, remember we created the entrypoint definition? Well, we need some code to back that.
Code:
DllEntryPoint:
  mov eax,1 ;No reason to fail, so return true
  retn 0xC  ;STDCALL
DLL Entry points in Windows are always STDCALL, and take 3 DWORD arguments, meaning 12 (0xC) bytes of arguments. Use "retn 0xC" for this. EAX is the return value.

Next, we define the functions. We will use this, that I have just written now Wink
Code:
info_title db 'Information',0 ;Null-terminated

ShowStr: ;CDECL; arguments: String, HWND; no stack frame; returns double
  push MB_ICONINFORMATION or MB_YESNO
  push info_title
  push dword[esp+0xC] ;Push the first argument -
                      ;keep track of stack usage if you don't use a frame pointer
  fld qword[esp+0x14] ;Get double-type argument
  sub esp,4           ;Push nothing
  fistp dword[esp]    ;Store the double as an integer at the top of the stack
  call [MessageBox]   ;Be careful what you reference as a pointer and what you reference directly.
  push eax            ;Move return value to the top of the stack
  fild dword[esp]     ;Load EAX as a double to be returned
  pop eax             ;Pop the stack back to normal
  ret ;CDECL calling convention - use retn 0xC for STDCALL

ShowInt: ;STDCALL; arguments: Number, HWND; stack frame; returns double
  push ebp
  mov ebp,esp          ;Set up stack frame
  push ebx             ;Save ebx
  sub esp,0xC          ;Allocate 3 DWORD local variables
  fld qword[ebp+0x8]   ;Get first double-type argument
  fistp dword[ebp-0x4] ;Store in first local variable
  fld qword[ebp+0x10]  ;Get second double-type argument
  fistp dword[ebp-0x8] ;Store in second local variable
  push 0x10            ;Allocate a 16-byte buffer
  push GPTR            ;Initialize to zero
  call [GlobalAlloc]
  mov [ebp-0xC],eax    ;Save return value in local var
  mov word[eax],'0x'   ;Prefix our number
  inc eax
  inc eax
  mov ebx,eax          ;Change registers.
  mov cl,8             ;Loop 8x
  mov edx,[ebp-0x4]    ;First variable, integer form of first argument

@@:                    ;Anonymous label
  rol edx,4            ;Get topmost hex digit
  mov al,dl
  and al,0xF           ;Get only this digit
  cmp al,0xA
  sbb al,0x69
  das                  ;Convert to ASCII
  mov byte[ebx],al     ;Store our current char
  inc ebx              ;Move to next char
  dec cl               ;Loop counter ;) Dec/Jnz is oddly faster than Loopd
  jnz @b               ;If ECX is not zero, jump to previous anonymous label
  mov byte[eax],cl     ;Make use of our already-0 register to optimize for size
                       ;and terminate the string ;)
  push MB_ICONERROR    ;Do not OR with any button values to make "OK only".
  push info_title
  push dword[ebp-0xC]  ;Push generated string
  push dword[ebp-0x8]  ;Push HWND
  call [MessageBox]    ;Show it! :)
  push dword[ebp-0xC]  ;Push memory area
  call [GlobalFree]    ;Free it
  fldz ;Load 0 onto floating-point stack - to be returned
  pop ebx
  leave ;Destroy stack frame
  retn 0x10 ;STDCALL. 0x10 = 2 arguments of "double" type (0x8 bytes)
Note that I do not expect you to understand what "sbb" or "das" do. You just need to know that the routine which includes it converts one hex digit to ASCII format. Notice also that I leave string constants at the start of the function. All strings, as you should already know, are passed as pointers and are for the most part null-terminated. Since this string is constant, it does not harm to continually re-use the same one. It's also in a non-writable area - always a plus.

If you don't understand why I do something even after reading the comments, please just post.

Now, we need to import those functions we used. You can't use them without asking politely Wink :
Code:
section '.idata' import data readable writeable

;Self-explanatory:

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         GlobalAlloc,'GlobalAlloc',\
         GlobalFree,'GlobalFree'

  import user,\
         MessageBox,'MessageBoxA'
Note that you don't have to use the same function names - I called my function MessageBox, yet it was calling MessageBoxA from User32.DLL. You could rename the "MessageBox" (the one not in quotes) to anything, as it is merely a variable which is filled in on DLL load.

Now, how does Windows know which function is which? It doesn't. We tell it like this:
Code:
section '.edata' export data readable

;Exports:

  export 'example.dll',\
         ShowInt,'ShowInt',\
         ShowStr,'ShowStr'
That will export our functions. In quotes is the exported name, not in quotes is the internal name (which is not put in the compiled EXE). I have called this DLL "example.dll", but it doesn't matter what you put there. I'm not entirely sure why Windows wants us to put that there, it's most likely something to do with the way GetModuleHandle resolves module names.

And now, we need to cover our back for if our DLL's address space is already taken!
Code:
section '.reloc' fixups data discardable
;Auto-generated
That's all you need - that will write some metadata to the DLL telling Windows what opcodes to change if it loads the DLL to a different address.

That's it. Not much more than that. Bear in mind that every section is a multiple of 512 bytes, so if you create a whole section with one variable, the variable will take up 512 bytes. If you use 513 bytes, then the section will be 1KB (1024 bytes).

There's your high-speed tutorial, most info is in the comments in that DLL that I carelessly wrote in 5 minutes Wink


Now, here's the entire code for if you don't want to piece together and just want something to play with right now: (Download)
Code:
format PE GUI 4.0 DLL
entry DllEntryPoint
include 'win32a.inc'

section '.text' code readable executable

DllEntryPoint:
  mov eax,1 ;No reason to fail, so return true
  retn 0xC  ;STDCALL

info_title db 'Information',0 ;Null-terminated

ShowStr: ;CDECL; arguments: String, HWND; no stack frame; returns double
  push MB_ICONINFORMATION or MB_YESNO
  push info_title
  push dword[esp+0xC] ;Push the first argument -
                      ;keep track of stack usage if you don't use a frame pointer
  fld qword[esp+0x14] ;Get double-type argument
  sub esp,4           ;Push nothing
  fistp dword[esp]    ;Store the double as an integer at the top of the stack
  call [MessageBox]   ;Be careful what you reference as a pointer and what you reference directly.
  push eax            ;Move return value to the top of the stack
  fild dword[esp]     ;Load EAX as a double to be returned
  pop eax             ;Pop the stack back to normal
  ret ;CDECL calling convention - use retn 0xC for STDCALL

ShowInt: ;STDCALL; arguments: Number, HWND; stack frame; returns double
  push ebp
  mov ebp,esp          ;Set up stack frame
  push ebx             ;Save ebx
  sub esp,0xC          ;Allocate 3 DWORD local variables
  fld qword[ebp+0x8]   ;Get first double-type argument
  fistp dword[ebp-0x4] ;Store in first local variable
  fld qword[ebp+0x10]  ;Get second double-type argument
  fistp dword[ebp-0x8] ;Store in second local variable
  push 0x10            ;Allocate a 16-byte buffer
  push GPTR            ;Initialize to zero
  call [GlobalAlloc]
  mov [ebp-0xC],eax    ;Save return value in local var
  mov word[eax],'0x'   ;Prefix our number
  inc eax
  inc eax
  mov ebx,eax          ;Change registers.
  mov cl,8             ;Loop 8x
  mov edx,[ebp-0x4]    ;First variable, integer form of first argument

@@:                    ;Anonymous label
  rol edx,4            ;Get topmost hex digit
  mov al,dl
  and al,0xF           ;Get only this digit
  cmp al,0xA
  sbb al,0x69
  das                  ;Convert to ASCII
  mov byte[ebx],al     ;Store our current char
  inc ebx              ;Move to next char
  dec cl               ;Loop counter ;) Dec/Jnz is oddly faster than Loopd
  jnz @b               ;If ECX is not zero, jump to previous anonymous label
  mov byte[eax],cl     ;Make use of our already-0 register to optimize for size
                       ;and terminate the string ;)
  push MB_ICONERROR    ;Do not OR with any button values to make "OK only".
  push info_title
  push dword[ebp-0xC]  ;Push generated string
  push dword[ebp-0x8]  ;Push HWND
  call [MessageBox]    ;Show it! :)
  push dword[ebp-0xC]  ;Push memory area
  call [GlobalFree]    ;Free it
  fldz ;Load 0 onto floating-point stack - to be returned
  pop ebx
  leave ;Destroy stack frame
  retn 0x10 ;STDCALL. 0x10 = 2 arguments of "double" type (0x8 bytes)

section '.idata' import data readable writeable

;Self-explanatory:

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL'

  import kernel,\
         GlobalAlloc,'GlobalAlloc',\
         GlobalFree,'GlobalFree'

  import user,\
         MessageBox,'MessageBoxA'

section '.edata' export data readable

;Exports:

  export 'example.dll',\
         ShowInt,'ShowInt',\
         ShowStr,'ShowStr'

section '.reloc' fixups data discardable
;Auto-generated
We need ASM syntax highlighting. Grin

It might help if you use Wikipedia to look at x86 calling conventions.
Oh, I forgot to mention that I'm pretty familiar with WinAPI - if you're not, you just need to look in MSDN for each function. I suggest you turn on Low Bandwidth view too, because otherwise it's a pain to use (especially scrolling in firefox).
« Last Edit: September 03, 2009, 01:20:23 PM by Score_Under » Logged

But captain obvious jumped to conclusions and said i didn't know C++.
xot
Administrator
Jr. Member
*****

Karma: +0/-0
Offline Offline

Posts: 54



View Profile WWW
« Reply #1 on: September 06, 2009, 11:36:44 PM »

Quote
This assumes a prior knowledge of 32-bit Intel Syntax ASM.

I've been a self-taught hobbyist programmer for over 25 years. I've got some assembly experience in other architectures, mainly 6502 on various platforms. It would be more accurate to say I have a lot of disassembly experience and a lot of hand-assembly experience; I've never actually used a proper macro assembler. I've also ported some 68000 in years past, although I've never coded it myself. I feel comfortable with the basics of assembly (if not assemblers) and have a solid understanding of how computers actually work. What can you recommend for someone like me if they wanted to get started with x86?
« Last Edit: September 06, 2009, 11:43:25 PM by xot » Logged


Score_Under
Jr. Member
**

Karma: +2/-0
Offline Offline

Posts: 62


View Profile Email
« Reply #2 on: September 09, 2009, 04:05:50 PM »

What can you recommend for someone like me if they wanted to get started with x86?
Ah, if you love disassembly as much as I do, you should check out Ollydbg (linked in the first post). That is a very fun tool to play with, so long as you understand.

Anyway, if you are just looking for basics, then it's pretty much: (Also writing this with those who have not used much ASM in mind, as other people may read this Wink )
Almost any register can be used for anything.
MOV DEST,SRC - Sets dest to src
Registers (in order): EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI.
AX is the least significant 2 bytes of EAX (the 16-bit equivalents of the registers are just the register names without the "E")
AL is the least significant byte of EAX, and AH is the next one up after that (AH<<8 | AL = AX).
You can use AL, AH, CL, CH, DL, DH, BL, and BH in this manner. ESP, EBP, ESI, and EDI have no equivalent to this.

All arithmetic and bit-manipulation instructions set relevant flags in the flag register.

ADD DEST,SRC - Adds src to dest.
XADD DEST,SRC - Adds src to dest, stores old value of dest in src.
SUB DEST,SRC - Subtracts src from dest.
MUL SRC - Multiplies EAX by src, stores lower 32 bits of result in EAX and higher 32 bits in EDX.
DIV SRC - Divides EAX by src, stores result in EAX and modulus in EDX.
AND DEST,SRC - Performs bitwise AND. (You get the dest/src idea by now Wink )
OR DEST,SRC - Performs bitwise OR.
XOR DEST,SRC - Performs bitwise XOR.
NOT DEST - Performs bitwise NOT.
SHL DEST,AMT - Shifts dest left by amt bits (C equivalent: dest=dest<<amt; )
SHR DEST,AMT - Shifts dest right by amt bits.
ROL DEST,AMT - Rotates dest left by amt bits. (Like shifting but wraps to the other side)
ROR DEST,AMT - Rotates dest right by amt bits.
XCHG FIRST,SECOND - Swaps 2 values. (E.g. XCHG EAX,EDX. XCHG [mem_ref],AL)
DEC DEST - Subtract 1 from dest (Same as C's dest--; )
INC DEST - Add 1 to dest.
NEG DEST - Set dest to 0-dest.
CMP FIRST,SECOND - Like SUB, but doesn't save the result, only the flags.
TEST FIRST,SECOND - Like CMP, but performs AND.

You can have a maximum of one memory reference per instruction, and it is used like so:
MOV EAX,[mem_ref]
In this case, since we're setting EAX, the size is an implied DWORD. If we were using:
MOVZX EAX,[mem_ref]
(MOVZX being like MOV but extends a smaller data size to 32 bits by setting the unused bytes of those 32 bits to 0). This is invalid, as we could be referencing a WORD or a BYTE.
MOVZX EAX,WORD[mem_ref]
That would be valid. Remember that it does no harm to specify the type of memory you are referencing.
You can of course use it the other way around:
MOV DWORD[mem_ref],EAX

This is also valid - compare:
MOVZX EAX,AL
with:
AND EAX,0xFF

Now, I know I've not structured this well, so you'll have to bear with me.
The registers are named:
EAX = Accumulator (although not strictly - registers are pretty much interchangable)
ECX = Loop Counter (loopd instruction, although that's slower than the "normal" equivalent!)
EDX = Data (Alternative to accumulator in mul/div, etc)
EBX ... ?
ESP = Stack Pointer
EBP = Stack base pointer (frame pointer)
ESI = Source indicator (for string instructions)
EDI = Destination indicator (for string instructions)

Now, assuming knowledge of a stack:
PUSH SRC - (Subtracts 4 from ESP, then) Pushes the value onto the stack as 32-bit.
POP DEST - Pops the value off the stack (, then adds 4 to ESP).
LEAVE - Same effect as MOV ESP,EBP then POP EBP.
ENTER X,Y - Do not use - slower and larger equivalent of normal stack frame setup.

To set up a stack frame (exit it with LEAVE):
PUSH EBP
MOV EBP,ESP

You will see this at the beginning of most functions in programs generated by a compiler.

Now, before we get onto the most basic of instructions, let me pollute your mind with more silly things:
SAR - Like SHR but copies the value of the carry flag instead of zero. (If CF is 1, 00000000 SAR 1 = 10000000)
SAL - Like SHL but copies value of the carry flag instead of zero.
BT VALUE,BIT - Tests the specified bit in the value and stores the state of the bit in the Carry Flag. (BT EAX,0 checks if EAX is even, for example.)
BTC VALUE,BIT - Same as BT but sets the bit to 0 afterwards.
BTS VALUE,BIT - Same as BT but sets the bit to 1 afterwards.

Now, the useful instructions:
JMP value - changes the instruction pointer, and thus program flow, to the address you give. JMP mem_ref will execute the code at mem_ref, while JMP [mem_ref] will jump to the code that mem_ref points to.
CALL value - Same as JMP, but pushes the address of the instruction after the CALL.
RETN - Opposite of CALL: pops an address off the stack and jumps to it.
RETN xx - Like RETN, but adds xx to ESP (stack pointer) after returning. Useful for stdcall functions that take arguments.

Now, conditional instructions...
The conditions are: (Prefix with N to negate it - NE [not equal] is the opposite of E [equal])
Z, E = Zero, Equal
G, NLE = Greater than (signed)
L, NGE = Less than (signed)
A, NBE = Greater than (unsigned)
B, NAE = Less than (unsigned)
GE, NL = Greater than or equal to (signed)
LE, NG = Less than or equal to (signed)
AE, NB = Greater than or equal to (unsigned)
BE, NA = Less than or equal to (unsigned)
C = Carry flag is set
P, PO, NPE = Parity is odd
NP, NPO, PE = Parity is even
ECXZ = ECX is 0
CXZ = CX is 0
O = Integer overflow occured
S = Sign bit is set (... I think - not entirely sure as I've never used it)

You can use J[condition] as a conditional jump, like this:

MOV ECX,20
label:
DEC ECX
JNZ label ; jump if not zero. There is no JNECXZ, by the way.

The C equivalent of this is:
Code:
for(i=20;i;i--);

One rather special instruction that you may need for "Logical" NOT, and other logical instructions, is SET[condition] - like so:
Code:
test EAX,EAX
setnz AL
movzx EAX,AL
(Logical NOT of EAX)

SET[condition] sets a single-byte value (register or memory) to 1 if the condition is satisfied, otherwise 0.

Since I am not really a natural-born teacher, I wonder if I skipped anything. Either way, the next instructions you might like to learn would be string instructions:
REP STOSB - (if ECX is larger than 0) Stores AL into BYTE[EDI], increases EDI, decreases ECX, and loops until ECX is 0.
REPNE SCASB - (if ECX is larger than 0) Compares AL with BYTE[ESI], decreases ECX, increases ESI, and loops if ECX>0 and BYTE[ESI before we increased it]!=0

You can use those instructions without REP (or repne, etc), which removes looping and all references to ECX.
There are many more string instructions.

Another very useful instruction is LEA. It pretty much returns the address you used instead of the memory at that address. It is useful because it means you can perform quick arithmetic and move it into another register:
LEA EBX, [EAX+ECX*4+mem_location]

(C-style: ebx = eax + ecx*4 + &mem_location; )

Note that the address doesn't have to be valid:
XOR EAX,EAX
LEA EAX, [EAX*2+1]
This is valid, even though referencing that address would most likely cause a segfault.

If you need an instruction reference: http://www.rz.uni-karlsruhe.de/rz/docs/VTune/reference/About_IA-32_Instructions.htm

Though I'm pretty sure I missed... everything... those are the instructions you'll want to know.

(I definitely missed FPU instructions...)
I also forgot to mention that to return a string, you MOV EAX to equal a pointer to the string (and make sure the FPU stack is in the same position as it was when you started - but when you return a double, you have to have 1 more item on the FPU stack than when you started).
« Last Edit: September 14, 2009, 02:41:49 PM by Score_Under » Logged

But captain obvious jumped to conclusions and said i didn't know C++.
Brad
Newbie
*

Karma: +2/-0
Offline Offline

Posts: 10


View Profile Email
« Reply #3 on: November 13, 2009, 07:08:02 PM »

I have always wanted to learn how to do ASM.

This may be a very "nooby" question, but what are the main differences between 32-bit and 64-bit asm?

Also, maybe you could post some example tutorials (like "hello world" or whatever). I am the sort of person that learns a lot better by seeing a good example and then having the example explained in detail.
Logged

I know Gml, Mysql, PHP, HTML, Javascript, Visual Basic, Delphi and C++
Score_Under
Jr. Member
**

Karma: +2/-0
Offline Offline

Posts: 62


View Profile Email
« Reply #4 on: November 14, 2009, 08:59:31 AM »

This may be a very "nooby" question, but what are the main differences between 32-bit and 64-bit asm?
32-bit ASM does calculations and references pointers in 32-bit. It prefixes registers with "e".
64-bit ASM does most calculations and references pointers in 64-bit. It prefixes registers with "r".

For example, this code could be valid 32-bit ASM:
Code:
mov dword [0x10003501],eax
But you can access more memory, and store larger values by default using 64-bit ASM:
Code:
mov qword [0x0000000010003501],rax
(QWORD is 64 bits, and DWORD is 32 bits. This doesn't mean you can't perform an equivalent operation on 32-bit processors, though. The advantage with 64-bit processors is that you can calculate large numbers faster and that you can reference more memory).

In 64-bit ASM, you could do this:
Code:
movzx rax,eax
That would set RAX to EAX. Since EAX, in 64-bit ASM, is the lower 32-bit half of RAX, this is the same as ANDing RAX with 0x00000000FFFFFFFF.

I'm sorry that I'm not so good at explaining some things Wink

Anyway, the simplest "Hello World" I can think of in Flat Assembler using my preferred programming style is:
Code:
format PE GUI 4.0 ; This is the type of file to generate. FASM can assemble for Linux, DOS, and even bootloaders and your own invented-on-the-spot formats.
entry entrypoint ; entry <address> makes the program start at the address you state. We define "entrypoint" later in the program.
include 'include\win32a.inc' ; Default windows includes, containing things like the "import" and "library" macros.

section '.code' code import data executable readable writeable
library u32,'user32.dll'
import u32,MessageBox,'MessageBoxA'

title db "Title",0
msg db "Message",0
entrypoint: ;This is used in place of a literal address for the "entry" preprocessor directive near the start of the file.
  push 0
  push title
  push msg
  push 0
  call [MessageBox]
  ret
The first thing you should note is that the arguments here are pushed in reverse order (HWND is pushed last).
The next thing you should note is the brackets around MessageBox. This is because "MessageBox" is in fact a variable, set at runtime by Windows to the location of the actual function MessageBoxA (which we described in our import table). The brackets tell it not to call the variable (which isn't valid code), but the function it points to.

I know it's not "normal" to put the import table in the same section as the code, but it works. Wink

The "db" command is simple, "Declare Bytes". It defines each character in the following string as a byte. The reason we also put the byte "0" afterwards is because the string needs to be NULL-terminated, which ASM doesn't do for you (MessageBoxA takes C-style strings).
Logged

But captain obvious jumped to conclusions and said i didn't know C++.
Brad
Newbie
*

Karma: +2/-0
Offline Offline

Posts: 10


View Profile Email
« Reply #5 on: November 14, 2009, 01:15:01 PM »

Cool! I''l try some experimenting with that example.

ASM is very complicated. Did you learn it professionally, or were you self-taught?


Edit: I'm trying to experiment with the DLL example you posted. I am having trouble with the stack. Maybe you could also expand on how stacks work? Sorry for bothering you, but I have always wanted to learn ASM, and could never really find good resources for learning it. I hope you understand Smiley
« Last Edit: November 14, 2009, 02:14:12 PM by Brad » Logged

I know Gml, Mysql, PHP, HTML, Javascript, Visual Basic, Delphi and C++
IntangibleVirus
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 9


Game Enthusiast

intangiblevirus@gmail.com
View Profile Email
« Reply #6 on: November 14, 2009, 04:31:29 PM »

I have always wanted to learn ASM, and could never really find good resources for learning it. I hope you understand Smiley

http://en.wikibooks.org/wiki/X86_Assembly
Logged
Brad
Newbie
*

Karma: +2/-0
Offline Offline

Posts: 10


View Profile Email
« Reply #7 on: November 15, 2009, 12:06:33 AM »

Thanks, IntangibleVirus! Its a great resource.


edit:

I think I'm getting a hang of it. The only major problem I'm having right now is working with the "double" types that Game Maker passes to the function. Right now, I'm just experimenting with basic looping, addition, etc. but I would like to be able to work with the double precision values passed from Game Maker. Maybe someone could elaborate on how to use the FPU stack.

Oh. And some info on how the EBP register works would be great! What exactly is the purpose of a "base pointer"?


Maybe you'll have a whole documentation on x86 asm on this thread soon  Grin
« Last Edit: November 15, 2009, 01:59:05 PM by Brad » Logged

I know Gml, Mysql, PHP, HTML, Javascript, Visual Basic, Delphi and C++
Score_Under
Jr. Member
**

Karma: +2/-0
Offline Offline

Posts: 62


View Profile Email
« Reply #8 on: November 15, 2009, 05:15:03 PM »

Oh. And some info on how the EBP register works would be great! What exactly is the purpose of a "base pointer"?
All registers are pretty much general purpose - EBP's use is determined by the program, though it is most often used to point to a place in the stack at [return address - 4]. This is usually to protect against any "damage" a poorly-written function (e.g. in a DLL) might cause to the stack.
Logged

But captain obvious jumped to conclusions and said i didn't know C++.
Pages: [1]   Go Up Print
 
Jump to:  

 
     
Powered by MySQL Powered by PHP Powered by SMF 1.1.10 | SMF © 2006-2009, Simple Machines LLC
Theme by Roach
Valid XHTML 1.0! Valid CSS!