assign memory location to register assembly - memory

Let's say for example I have four specific memory addresses that each hold a 32-bit integer. How would you use assembly language to take the address and assign it register %eax?
Would it be movl 0x12AED567, %eax?

Yes, it is that simple. If you already have the addresses, just assign them to eax, I corrected your code a little :
mov 12AED567h, eax
But, if you want to get the addresses dynamically, you have to use lea instruction, next little program shows how :
.stack 100h
.data
my_number dd A01Ch
.code
;INITIALIZE DATA SEGMENT.
mov ax,#data
mov ds,ax
;GET THE MEMORY ADDRESS OF MY_NUMBER, NOT THE NUMBER ITSELF.
lea eax, my_number
;FINISH THE PROGRAM PROPERLY.
mov ax,4c00h
int 21h
Is this what you were looking for?
By the way, this is 8086 assembler with Intel's syntax.

Related

Understanding calling convention and stack pointer

I want to understand how should I use local variables and how to pass arguments to function in x86. I read a lot of guides, and they all wrote that the first parameter should be at [ebp+8], but it isn't here :/ WHat am I missing? What am I not understanding correctly?
number byte "724.5289",0
.code
main PROC
mov ebx,offset number ;making so that [ebp] = '7' atm
push ebx ;I push it on stack so I can access it inside the function
call rewrite
main ENDP
rewrite PROC
push ebp ; push ebp so we can retrieve later
mov ebp, esp ; use esp memory to retrieve parameters and
sub esp, 8 ; allocate data for local variable
lea ebx, [ebp-8]
lea eax, [ebp+8] ; i think here ebp+8 should point to the same now to which ebx did
;before function, but it does not, writechar prints some garbage ascii character
call writechar
call crlf
rewrite ENDP
END main
You pass a pointer as argument to rewrite, and then pass its address on to writechar. That is you take the address twice. That is one too many :)
You want mov eax, [ebp+8] instead of lea eax, [ebp+8]
Also, you need to clean up the stack after yourself, which you don't do. Furthermore, make sure your assembler automatically emits a RET for the ENDP directive, otherwise you will be in trouble. You might want to write it out explicitly.

Change the value at an absolute word address

How do you perform operations like change the value at an absolute word address?
Say you have some value at 5DAh and you want to count the number of zeros on that address, or move a value from one absolute address to another. How can one do that?
Short Answer: You Can't
You might have a trick question in front of you (no clue, just my guess).
The physical architecture of the 8086 chip did not have that instruction.
As for your two specific questions...
"...you want to count the number of zeros on that address..."
That's somewhat ambiguous, in fact so vague that I can't understand it.
"...move a value from one absolute address to another..."
Good question. We'll do this in 32 bit, no, 16 and then 32 bit.
16 bit example
Push Si ;source index register
Push Di ;destination index register
Push Ax ;We'll use this for the transfer
Lea Si, Where_The_Number_Is_Now ;You'll define this, somehow
Lea Di, Where_We_Want_It_To_Go ;You'll define this also, same thing
Mov Ax, Ds:[Si] ;The "Ds:" may or may not be needed, be safe
Mov Ds:[Di], Ax ;Probably do need "Ds:" for this instruction
Pop Ax ;Do pay attention to the reverse order
Pop Di ;...of popping the registers in exact
Pop Si ;...opposite of how they were pushed
; And you are done
32 bit example
Push Esi ;source index register
Push Edi ;destination index register
Push Eax ;We'll use this for the transfer
Lea Esi, Where_The_Number_Is_Now ;You'll define this, somehow
Lea Edi, Where_We_Want_It_To_Go ;You'll define this also, same thing
Mov Eax, Ds:[Esi] ;The "Ds:" may or may not be needed, be safe
Mov Ds:[Edi], Eax ;Probably do need "Ds:" for this instruction
Pop Eax ;Do pay attention to the reverse order
Pop Edi ;...of popping the registers in exact
Pop Esi ;...opposite of how they were pushed
; And you are done
To change a value at an absolute word address:
mov byte ptr [5dah], 0
...or...
mov word ptr [5dah], 0
To move a value from one absolute word address to another:
mov al, byte ptr [5dah]
mov byte ptr [1234h], al
...or...
mov ax, word ptr [5dah]
mov word ptr [1234h], ax
As for the other question, the one that asked how to count the number of zeros on that address, you were a little to vague.

Read command line in assembly

First time I play with ds, si and strings related instructions in assembly. I am trying to read the command line arguments char by char and this is how my code looks like now:
GetCommandLine:
push ebp
mov ebp, esp
push edi
push esi
call GetCommandLineW
mov edi, eax
mov esi, ebp
Parse:
lodsw
cmp ax, 0dh ; until return is found
jne Parse
pop esi
pop edi
pop ebp
ret
So, the GetCommandLineW function returns a correct pointer to the string. The problem is that the Parse section loops forever and I can't see the AX register being loaded with the correct next byte from the string. I think the EDI:ESI is not correctly loaded or something
esi and edi are different pointers. ebp is used for saving the old stack pointer, and for saving/loading local variables. GetCommandLineW will return the pointer in eax, which you should then put into esi. Since you're only using lodsw (and not stos*), you don't need to touch edi.
Why do you think that 0x0d is used in the commandline? A normal C string is returned, so you should look for a 0 byte.

Modifying a byte in memory using shellcode

I have been trying to create a simple chunk of shell code that allows me to modify a string by doing something simple like changing a letter, then print it out.
_start:
jmp short ender
starter:
xor ecx, ecx ;clear out registers
xor eax, eax
xor ebx, ebx
xor edx, edx
pop esi ;pop address of string into esi register
mov byte [esi+1], 41 ;try and put an ASCII 'A' into the second letter of the string
;at the address ESI+1
mov ecx, esi ;move our string into the ecx register for the write syscall
mov al, 4 ;write syscall number
mov bl, 1 ;write to STDOUT
mov dl, 11 ;string length
int 0x80 ;interrupt call
ender:
call starter
db 'hello world'
It's supposed to print out "hallo world". The problem occurs (segfault) when I try and modify a byte of memory with a mov command like so.
mov byte [esi+1], 41
I ran the program though GDB and the pop esi command works correctly, esi is loaded with the address of the string and everything is valid. I can't understand why I cant modify a byte value at the valid address though. I am testing this "shellcode" by just running the executable generated by NASM and ld, I am not putting it in a C program or anything yet so the bug exists in the assembly.
Extra information
I am using x64 Linux with the following build commands:
nasm -f elf64 shellcode.asm -o shellcode.o
ld -o shellcode shellcode.o
./shellcode
I have pasted the full code here.
If I had to guess, I'd say dbhello world` is being compiled in as code, rather than data, and as such has read and execute permissions, but not write ones. So you're actually falling foul of page protection.
To change this, you need to place the string in a section .data section and use nasm's variable syntax to find it. In order to modify the data as is, you're going to need to make a mprotect call to modify the permissions on your pages, and write to them. Note: these won't persist back to the executable file - mmap()'s MAP_PRIVATE ensures that's the case.

Create a pointer to a specific location

I need a pointer to location which is always the same. So, how can I create a pointer to.. lets say memory address 0x20 and store it in some way to be able to access it later.
Note:
I do NOT want to store the result, but the actual pointer to the memory address (since I want to point to the beginning of an array).
Thanks in advance.
--
I think I have fixed it now. I use bios interrupt 0x15 to get a memory map. Every interrupt returns 1 entry and you provide a pointer in es:di to a place where the bios can store it. I let the bios build it up from 050h:0h. I needed a pointer to 0x50:0x0 (0x500 linear) to use the map later. I still have to test, but I did the following:
mov ax, 0x50
mov es, ax
xor di, di
shl ax, 4
add ax, di
mov [mmr], ax
And mmr is declared this way:
mmr:
dw 0 ; pointer to the first entry
db 0 ;entry count
db 24 ; entry size
A pointer is just a memory address and a memory address is just a number. Assembly is not a typed language so there is no difference.
Also assembly doesn't really have variables. It has registers and memory locations, both of which can be used for storing values, including addresses/pointers.
So basically there are many variants of the x86 MOV instruction that can store a pointer such as 0x20 in an address or a register. You certainly want to think about whether you're doing 32-bit or 64-bit x86 assembly though (or 16-bit or even 8-bit for that matter).
x86:
suppose you have an array called list
mov bx, offset list
now, in the bx register you will have a pointer to the first memory location of list
to refer to the data in the memory location you would use [bx]
here's an brief example using intel syntax:
;declare list in .data
list dw 0123h
;move 01h from memory to ax register (16-bit)
mov bx, offset list
mov al, [bx] ; al = 23h
If you want to use the pointer later you can do this:
push bx then pop bx when you want to use it
or
mov point, bx ; declared in mmr

Resources