I'm new to x86.
I know what this kind of thing with the pointers means.
*command* %eax, %ebx
But how are these different, and what do they mean?
*command* %eax, (%ebx)
*command* (%eax), %ebx
*command* (%eax, %ebx, 4), %ecx
I think your question is, "what does the parentheses around a register's name mean/do?" At a high level, the parentheses say to perform a load from a memory address in and use that value in the instruction. Ie, whereas
*command* %eax, %ebx
operates on the values in the %eax and %ebx registers directly,
*command* (%eax), (%ebx)
loads the values from memory pointed to by %eax and %ebx and operates on them. There are actually a few more variants of the parentheses than you listed. For a description of them (including the last instruction example that you asked about), check here.
Hope that helps. Feel free to post back if you have any more questions.
Assume the following operations:
movl %eax, (%ebx) [1]
movl (%eax), %ebx [2]
movl (%eax, %ebx, 4), %ecx [3]
1, The first one will copy the value of eax into an address stored in ebx, smiler to this in C:
*(int *)ebx = eax; // copy eax into address
2, The second will copy the value stored in an address at eax into ebx:
ebx = *(int *)eax; // copy what in address into ebx
3, This is an array operation, where ebx is the index and 4 is the size of an element of the array.
ecx = ((int *) p)[ebx];
calculated as:
ecx = *(int *)((char *)p + ebx * sizeof(int));
In AT&T asm syntax, parenthesis mean "dereference" -- roughly the same as the unary * operator in C. So some rough equivalences:
movl %eax, %ebx eax = ebx
movl %eax, (%ebx) eax = *ebx
movl (%eax), %ebx *eax = ebx
That leqaves your last example:
movl (%eax, %ebx, 4), %ecx
In this case, there are multiple values that are combined to form the address to dereference. It's roughly equivalent to
*(eax + ebx*4) = ecx
Related
I am trying to code a recursive fibonacci sequence in assembly, but it is not working for some reason.
It does not give an error, but the output number is always wrong.
section .bss
_bss_start:
; store max iterations
max_iterations resb 4
_bss_end:
section .text
global _start
; initialise the function variables
_start:
mov dword [max_iterations], 11
mov edx, 0
push 0
push 1
jmp fib
fib:
; clear registers
mov eax, 0
mov ebx, 0
mov ecx, 0
; handle fibonacci math
pop ebx
pop eax
add ecx, eax
add ecx, ebx
push eax
push ebx
push ecx
; incriment counter / exit contitions
inc edx
cmp edx, [max_iterations]
je print
; recursive step
call fib
ret
print:
mov eax, 1
pop ebx
int 0x80
For instance, the above code prints a value of 79 rather than 144 (11th fibonacci number).
Alternatively, if I make
mov dword [max_iterations], 4
Then the above code prints 178 rather than 5 (5th fibonacci number).
Any one have an idea?
K
As an approach, you should try to debug it with the smallest possible input, like 1 iteration. That will be most revealing as you can watch it do the wrong thing in great detail without worrying about multiple recursing's. When that works, go to 2 iterations.
When you use complex addressing modes, it is harder to debug as we cannot see what the processor is doing. So, when an instruction using a complex addressing mode doesn't work, and you want to debug it, then split that instruction into 2 instructions as follows:
mov dword [fibonacci_seq + edx + 4], ecx
---
lea esi, [fibonacci_seq + edx + 4]
mov [esi], ecx
With the alternate code sequence, you can observe the value of the addressing mode computation, which will provide you with additional debugging insight.
As another example:
cmp edx, [max_iterations]
---
mov edi, [max_iterations]
cmp edx, edi
Using the 2 instruction version, you will be able to see what value the processor is comparing edx with.
Or better, do that that mov load once before the loop, so you're keeping the loop bound in a register all the time. That's what you should normally do when you have enough registers, only using memory when you run out.
You are jmping to fib from one place in the code and calling it from another. Though your logic should work because when you've reached the limit, you don't return to the main, this is really bad form: to mix main code with function. More on that below...
mov dword [fibonacci_seq + edx + 4], ecx
Is this working for you? You're only incrementing edx by 1. Perhaps you wanted:
mov dword [fibonacci_seq + edx * 4], ecx
I would argue that your code is not really recursive.
call fib ; jumps to fib, pushes a return address
ret ; never, ever reached, so, pointless
---
jmp fib ; iterate w/o pushing unwanted return address onto the stack
The 1-instruction jmp will be superior to the call as a mechanism to iterate, in part b/c it doesn't push an unnecessary return address onto the stack.
When you debug with 2 iterations, you'll probably see that the unused return address pushed by the call messes up your "parameter" passing, pops.
To expand on the "recursion", when the iteration stops and control transfers to print, there will be some 11 (depending on iteration count) unused return addresses on the stack (modulo the interference by the pop's and pushes).
The recursive call is only used for iteration, the recursion never unwinds. Thus, I would argue it's not recursive (not even tail recursive) — it just erroneously pushes some unused return addresses onto the stack — that's not recursion.
This line is your main problem:
mov dword [fibonacci_seq + edx + 4], ecx
Because of the +4, you never write to the first entry of the "array". And because you only increment EDX by 1, each write to the array overwrites 3 bytes of the previous entry. Try this instead:
mov dword [fibonacci_seq + edx * 4], ecx
A bit of redesign, as I did not realise that the call instruction used the stack in this way, and the solution is here
section .bss
_bss_start:
; store max iterations and current iteration
max_iterations resb 4
iteration resb 4
; store arguments
n_0 resb 4
n_1 resb 4
_bss_end:
section .text
global _start
; initialise the function variables
_start:
mov dword [max_iterations], 11
mov dword [iteration], 0
mov dword [n_0], 0
mov dword [n_1], 1
jmp fib
fib:
mov ecx, 0
mov edx, 0
mov eax, [n_0]
mov ebx, [n_1]
add ecx, eax
add ecx, ebx
mov edx, [n_1]
mov dword [n_0], edx
mov dword [n_1], ecx
mov edx, [iteration]
inc edx
mov dword [iteration], edx
cmp edx, [max_iterations]
je print
call fib
ret
print:
mov eax, 1
mov ebx, [n_1]
int 0x80
This is more an academic exercise than anything else, but I'm looking to write a recursive function in assembly, that, if it receives and "interrupt signal" it returns to the main function, and not just the function that invoked it (which is usually the same recursive function).
For this test, I'm doing a basic countdown and printing one-character digits (8...7...6...etc.). To simulate an "interrupt", I am using the number 7, so when the function hits 7 (if it starts above that), it will return a 1 meaning it was interrupted, and if it wasn't interrupted, it'll countdown to zero. Here is what I have thus far:
.globl _start
_start:
# countdown(9);
mov $8, %rdi
call countdown
# return 0;
mov %eax, %edi
mov $60, %eax
syscall
print:
push %rbp
mov %rsp, %rbp
# write the value to a memory location
pushq %rdi # now 16-byte aligned
add $'0', -8(%rbp)
movb $'\n', -7(%rbp)
# do a write syscall
mov $1, %rax # linux syscall write
mov $1, %rdi # file descriptor: stdout=1
lea -8(%rbp), %rsi # memory location of string goes in rsi
mov $2, %rdx # length: 1 char + newline
syscall
# restore the stack
pop %rdi
pop %rbp
ret;
countdown:
# this is the handler to call the recursive function so it can
# pass the address to jump back to in an interrupt as one of the
# function parameters
# (%rsp) currntly holds the return address, and let's pass that as the second argument
mov %rdi, %rdi # redundant, but for clarity
mov (%rsp), %rsi # return address to jump
call countdown_recursive
countdown_recursive:
# bool countdown(int n: n<10, return_address)
# ...{
push %rbp
mov %rsp, %rbp
# if (num<0) ... return
cmp $0, %rdi
jz end
# imaginary interrupt on num=7
cmp $7, %rdi
jz fast_ret
# else...printf("%d\n", num);
push %rsi
push %rdi
call print
pop %rdi
pop %rsi
# --num
dec %rdi
# countdown(num)
call countdown_recursive
end:
# ...}
mov $0, %eax
mov %rbp, %rsp
pop %rbp
ret
fast_ret:
mov $1, %eax
jmp *%rsi
Does the above look like a valid approach, passing the memory address I want to go back to in rsi? The function was incredibly tricky for me to write, but I think mainly due to the fact that I'm pretty new/raw with assembly.
As well as returning to this alternate return address, you also need to restore the caller's (call-preserved) registers, not just the ones of your most recent parent. That includes RSP.
You're basically trying to re-invent C's setjmp / longjmp which does exactly this, including resetting the stack pointer back to the scope where you called setjmp. I think a few of the questions in SO's setjmp tag are about about implementing your own setjmp / longjmp in asm.
Also, to make this more efficient you might want to use a custom calling convention where the return address pointer (or a jmpbuf pointer after implementing the above) is in a call-preserved register like R15, so you don't have to save/restore it around print calls inside the body of your recursive function.
I started to code in NASM assembly lately and my problem is that I don't know how I access struct elements the right way. I already searched for solutions on this site and on google but everywhere I look people say different things. My program is crashing and I have the feeling the problem lies in accessing the structs.
When looking at the example code:
STRUC Test
.normalValue RESD 1
.address RESD 1
ENDSTRUC
TestStruct:
istruc Test
at Test.normalValue dd ffff0000h
at Test.address dd 01234567h
iend
;Example:
mov eax, TestStruct ; moves pointer to first element to eax
mov eax, [TestStruct] ; moves content of the dereferenced pointer to eax (same as mov eax, ffff0000h)
mov eax, TestStruct
add eax, 4
mov ebx, eax ; moves pointer to the second element (4 because RESD 1)
mov eax, [TestStruct+4] ; moves content of the dereferenced pointer to eax (same as mov eax, 01234567h)
mov ebx, [eax] ; moves content at the address 01234567h to ebx
Is that right?
Help is appreciated
I dont know if you figured out but here is our code with some little modification that works. All instructions are correct except the last one mov ebx, [eax] which is expected caus you are trying to access content at address 0x1234567 resulting in SIGSEGV
section .bss
struc Test
normalValue RESD 1
address RESD 1
endstruc
section .data
TestStruct:
istruc Test
at normalValue, dd 0xffff0000
at address, dd 0x01234567
iend
section .text
global _start
_start:
mov eax, TestStruct ; moves pointer to first element to eax
mov eax, [TestStruct] ; moves content of the dereferenced pointer to eax same as mov eax, ffff0000h
mov eax, TestStruct
add eax, 4
mov ebx, eax ; moves pointer to the second element 4 because RESD 1
mov eax, [TestStruct+4] ; moves content of the dereferenced pointer to eax same as mov eax, 01234567h
mov ebx, [eax] ; moves content at the address 01234567h to ebx
Compile, link and run step by step with nasm -f elf64 main.nasm -o main.o; ld main.o -o main; gdb main
The C and assembly code:
long pcount_r(unsigned long x) {
if (x == 0) return 0;
else return (x & 1) + pcount_r (x>>1);
}
pcoutn_r:
movl $0, %eax
testq %rdi, %rdi
je .L6
pushq %rbx
movq %rdi, %rbx
andl $1, %ebx
shrq %rdi
call pcount_r
addq %rbx, %rax
popq %rbx
.L6:
rep; ret
If passing function a value x = 5 (binary representation is 0101). Register %rdi is the x value, and %rbx holds x value by "movq %rdi, %rbx" before pass "x>>1" to the next recursive call. Therefore, %rbx holds 0101, then 010, then 01.
The first call of pcount_r:
%rdi %rbx
0101 --> 0101
The second call of pcount_r:
%rdi %rbx
010 --> 010
The third call and etc...
%rbx can only hold one value at the time, To me, it seems just overwriting the previous value of %rbx, rather than saving data on a stack. My question is: how can %rbx restore the previous %rbx value when a recursive call ends?
more details about this function can be found in this link.
Recursive Procedures at time 55:00
I see. My mistake is that I thought register %rbx is holding the x value. But In fact, %rbx is just holding x value temporarily, assembly code "pushq %rbx" pushes %rbx value to the stack before passing the next %rdi to %rbx. Similarly, the value is restored by "popq %rbx".
I am re-writing an encryption/compression library and it seems like it is getting to be a lot of processing per bytes processed. I would prefer to use an enumeration type when choosing which of several limited ways the encryption can go (the proper way), but when those paths become cyclical, I have to add extra code to test for type'last and type'first. I can always just write such a condition in for the type, or assign the addition/subtraction operator on the type a function to wrap around the result, but that is more code and processing that will add up quickly when it has to run every eight bytes along with everything else. Is there a way to make the operation about as efficient as if it were a simple "mod" type, like
type Modular is mod 64 ....;
for ......;
pragma ....;
type Frequency_Counter is array(Modular) of Long_Integer;
Head : Modular := (others => 0);
Freq : Frequency_Counter(Size) := (others => 0);
Encryption_Label : Modular := Hash3;
Block_Sample : Modular := Hash5;
...
Hash3 := Hash3 + 1;
Freq (Hash3):= Freq(Hash3) + 1; -- Here is where my made-on-the-fly example is focused
I think I can make the whole algorithm more efficient and use enumeration types if I can just get the enumeration type to do math in the processor in the same number of cycles as with a mod type math. I have gotten a little creative in thinking of a way, but they were too obviously not right for me to use any of them as an example. The only thing I can think might be possible exceeds my skill, and that is making a procedure using inline ASM (gas assembly language syntax) to make the operation very direct to the processor.
PS: I know this is a minor gain, alone. Any gain is appropriate for the application.
Not sure that it’ll make much difference!
Given this
package Cyclic is
type Enum is (A, B, C, D, E);
type Modular is mod 5;
function Next_Enum (En : Enum) return Enum is
(if En = Enum'Last then Enum'First else Enum'Succ (En)) --'
with Inline_Always;
end Cyclic;
and
with Cyclic; use Cyclic;
procedure Cyclic_Use (N : Natural; E : in out Enum; M : in out Modular) is
begin
begin
for J in 1 .. N loop
E := Next_Enum (E);
end loop;
end;
begin
for J in 1 .. N loop
M := M + 1;
end loop;
end;
end Cyclic_Use;
and compiling using GCC 5.2.0 with -O3 (gnatmake -O3 -c -u -f cyclic_use.adb -cargs -S), the x86_64 assembler generated for the two loops is
(enumeration)
L3:
leal 1(%rsi), %ecx
addl $1, %eax
cmpb $4, %sil
cmove %r8d, %ecx
cmpl %eax, %edi
movl %ecx, %esi
jne L3
(modular)
L4:
leal -4(%rdx), %ecx
addl $1, %eax
cmpb $3, %dl
leal 1(%rdx), %r8d
movl %ecx, %edx
cmovle %r8d, %edx
cmpl %eax, %edi
jne L4
I don’t pretend to know x86_64 assembler, and I don’t know why the enumeration version compares against 4 while the modular version compares against 3, but these look very similar to me! but the enumeration version is one instruction shorter ...