I'm trying to write an x86-64 assembly program that is the function "int addarray(int n, int * array)". The first arg is the length of the array, second is a pointer to the array. It's supposed to add up the elements of the array and return. Here is the code I have so far, and I don't know why it doesn't work.
.text
.globl addarray
.type addarray, #function
addarray:
movq $0, %rdx
movq $0, %rax
while:
cmpq %rdx, %rdi
jle afterw
movq %rdx, %rcx
imulq $8, %rcx
addq %rsi, %rcx
addq %rcx, %rax
addq $1, %rdx
jmp while
afterw:
ret
I'm not real familiar with the AT&T syntax, but it looks like your line:
addq %rcx, %rax
Is going to add the value of rcx to rax. You want to add the value that rcx references, that is:
addq (%rcx), %rax
At least, I think that's how it's done in AT&T syntax. In Intel syntax, it would be:
add rax,[rcx]
There are a couple of simple optimizations you can do to speed things up somewhat, but I think the above is the key to your problem.
Related
I'm having trouble figuring out how to use printf correctly in this function. So the function is called multInts and is supposed to multiply the first element of the first array with the first element of the second array and continue through the whole array. However, the lab instructions specify that I can't call printf in the main function. So, I need to print out the word "Products:\n" and then in each new line after that, print out the product. I don't know how to use printf within the loop, however. The instructor said that we should "call printf in the loop after calculating product" and also to "save and restore caller-save registers before calling printf," but I'm not sure what that means.
Here's what my code looks like so far:
.file "lab4.s"
.section .rodata
.LC0:
.string "Products: \n"
.LC1:
.string "%i \n"
.data
sizeIntArrays:
.long 5
sizeShortArrays:
.word 4
intArray1:
.long 10
.long 25
.long 33
.long 48
.long 52
intArray2:
.long 20
.long -37
.long 42
.long -61
.long -10
##### MAIN FUNCTION
.text
.globl main
.type main,#function
main:
pushq %rbp
movq %rsp, %rbp
#pass parameters and call other functions
movl sizeIntArrays, %edi #move size to registers for 1st parameter
leaq intArray1, %rsi #load effective address of intArray1 to register rsi
leaq intArray2, %rdx #load effective address of intArray2 to register rdx
call multInts #call multInts function
movq $0, %rax #return 0 to caller
movq %rbp, %rsp
popq %rbp
ret
.size main,.-main
##### MULTINTS
.globl multInts
.type multInts,#function
multInts:
pushq %rbp
movq %rsp, %rbp
#add code here for what the functions should do
movq $0, %r8 #initialize index for array access in caller save reg
movq $0, %rcx #initialize 8 byte caller save result reg
loop0:
cmpl %r8d, %edi #compare index to size
je exit0 #exit if equal
movslq (%rsi,%r8,4),%rax # Load a long into RAX
movslq (%rdx,%r8,4),%r11 # Load a long into R11
imulq %r11, %rax # RAX *= R11
addq %rax, %rcx # RCX += RAX
incq %r8 #increment index
jmp loop0
exit0:
movq $.LC0, %rdi
movq %rcx, %rsi
movq $0, %rax
call printf
movq %rbp, %rsp
popq %rbp
ret
.size multInts,.-multInts
What I've tried to do is just move the printf instruction to before the loop, but it gives me a segmentation fault when trying to run the loop because %rdi and %rsi contain the addresses of the arrays that need to be used in the loop. How do I get around that and which registers should I use? Also, how do I call printf within the loop?
The output should look something like this:
Products:
200
-925
1386
-2928
-520
Assume that printf clobbers all the call-clobbered registers (What registers are preserved through a linux x86-64 function call), and use different ones for anything that needs to survive from one iteration of the loop to the next.
Look at compiler output for an example: write a version of your loop in C and compile it with -Og.
Obviously you need to move the instructions that set up the args in registers
(like the format string) along with the call printf.
The easiest way to protect a register from being accessed by a subroutine is to push it. According to the ABI V calling convention printf may change any register except RBX, RBP, R12–R15. The registers you need to preserve are RAX, RDX, RSI, RDI, R8 and R11 (RCX is no longer needed), so push before the call to printf and pop them afterwards:
pushq %rax
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r11
movq $.LC1, %rdi
movq %rax, %rsi
movq $0, %rax
call printf
popq %r11
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rax
Now, you can copy the block into the loop. For each printf, you have to think about what needs to be secured:
...
multInts:
pushq %rbp
movq %rsp, %rbp
#add code here for what the functions should do
pushq %rdx # Preserve registers
pushq %rdi
pushq %rsi
movq $.LC0, %rdi # Format string (no further values)
movq $0, %rax # No vector registers used
call printf # Call C function
popq %rsi # Restore registers
popq %rdi
popq %rdx
movq $0, %r8 #initialize index for array access in caller save reg
loop0:
cmpl %r8d, %edi #compare index to size
je exit0 #exit if equal
movslq (%rsi,%r8,4),%rax # Load a long into RAX
movslq (%rdx,%r8,4),%r11 # Load a long into R11
imulq %r11, %rax # RAX *= R11
pushq %rax # Preserve registers
pushq %rdx
pushq %rsi
pushq %rdi
pushq %r8
pushq %r11
movq $.LC1, %rdi # Format string
movq %rax, %rsi # Value
movq $0, %rax # No vector registers used
call printf # Call C function
popq %r11 # Restore registers
popq %r8
popq %rdi
popq %rsi
popq %rdx
popq %rax
incq %r8 #increment index
jmp loop0
exit0:
movq %rbp, %rsp
popq %rbp
ret
...
BTW: .string "%i \n" will force printf only to process the lower 32-bit of RDI. Use .string %lli \n instead.
I encountered the following code in my computer architecture class:
void mystery( long A[], long B[], long n )
{
long i;
for ( i = 0; i < n; i++ ) {
B[i] = A[n-(i+1)];
}
}
And my professor showed the corresponding assembly code GCC generates on an Ubuntu machine and he seems to be confused as well:
mystery:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -24(%rbp)
movq %rsi, -32(%rbp)
movq %rdx, -40(%rbp)
movq $0, -8(%rbp)
jmp .L2
.L3:
movq -8(%rbp), %rax
leaq 0(,%rax,8), %rdx
movq -32(%rbp), %rax
addq %rax, %rdx
movq -8(%rbp), %rax
notq %rax
movq %rax, %rcx
movq -40(%rbp), %rax
addq %rcx, %rax
leaq 0(,%rax,8), %rcx
movq -24(%rbp), %rax
addq %rcx, %rax
movq (%rax), %rax
movq %rax, (%rdx)
addq $1, -8(%rbp)
.L2:
movq -8(%rbp), %rax
cmpq -40(%rbp), %rax
jl .L3
popq %rbp
ret
But I can't understand why the compiler will generate this code. It appears the A, B, and n are pushed onto the stack but the stack pointer %rsp doesn't change its value. Also, -16(%rbp) also seems to be allocated but is never put in a value. Is there any reason GCC will behave this way?
Compiler Explorer (godbolt.org) is a great tool to look at generated assembly from various compilers and with different flags. Here's what g++7 -O2 produces for your code:
mystery(long*, long*, long):
test rdx, rdx
jle .L1
lea rax, [rdi-8+rdx*8]
sub rdi, 8
.L3:
mov rdx, QWORD PTR [rax]
sub rax, 8
add rsi, 8
mov QWORD PTR [rsi-8], rdx
cmp rax, rdi
jne .L3
.L1:
rep ret
To answer your question: compiling with optimizations disabled usually unexpected/less sensible output. "Why?" is a difficult question to answer as this highly depends on how the compiler is implemented.
Here's a screenshot showing a comparison of -O2, -O0 and -Ofast:
Try it out here: https://godbolt.org/g/pQ637a
Disclaimer: I'm just starting out with x86 assembly. I did learn a bit of SPIM at university, but that's hardly worth mentioning.
I thought I start with what's probably the most simple function in libc, abs(). Pretty straightforward in C:
long myAbs(long j) {
return j < 0 ? -j : j;
}
My version in assembly:
.global myAbs
.type myAbs, #function
.text
myAbs:
test %rdi, %rdi
jns end
negq %rdi
end:
movq %rdi, %rax
ret
(This doesn't work for 32bit integers, probably because RAX is a 64bit register and the sign is probably at the wrong position - I have to investigate that).
Now here's what gcc does (gcc -O2 -S myAbs.c):
.file "myAbs.c"
.section .text.unlikely,"ax",#progbits
.LCOLDB0:
.text
.LHOTB0:
.p2align 4,,15
.globl myAbs
.type myAbs, #function
myAbs:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $4144, %rsp
orq $0, (%rsp)
addq $4128, %rsp
movq %rdi, %rdx
sarq $63, %rdx
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movq %rdi, %rax
xorq %rdx, %rax
subq %rdx, %rax
movq -8(%rbp), %rcx
xorq %fs:40, %rcx
jne .L5
leave
.cfi_remember_state
.cfi_def_cfa 7, 8
ret
.L5:
.cfi_restore_state
call __stack_chk_fail#PLT
.cfi_endproc
.LFE0:
.size myAbs, .-myAbs
.section .text.unlikely
.LCOLDE0:
.text
.LHOTE0:
.ident "GCC: (Gentoo Hardened 5.1.0 p1.2, pie-0.6.3) 5.1.0"
.section .note.GNU-stack,"",#progbits
Why this big difference? GCC produces substantially more instructions. I can't imagine that this won't be slower than my code.
Am I missing something? Or am I doing something seriousely wrong here?
For those who wonder what the generated code comes from, first note that when GCC compile myAbs with stack protection it transform it into this form
long myAbs(long j) {
uintptr_t canary = __stack_chk_guard;
register long result = j < 0 ? -j : j;
if ( (canary = canary ^ __stack_chk_guard) != 0 )
__stack_chk_fail();
}
The code to simply perform j < 0 ? -j : j; is
movq %rdi, %rdx ;RDX = j
movq %rdi, %rax ;RAX = j
sarq $63, %rdx ;RDX = 0 if j >=0, 0fff...ffh if j < 0
xorq %rdx, %rax ;Note: x xor 0ff...ffh = Not X, x xor 0 = x
;RAX = j if j >=0, ~j if j < 0
subq %rdx, %rax ;Note: 0fff...ffh = -1
;RAX = j+0 = j if j >= 0, ~j+1 = -j if j < 0
;~j+1 = -j in two complement
Analyzing the generated code we get
pushq %rbp
movq %rsp, %rbp ;Standard prologue
subq $4144, %rsp ;Allocate slight more than 4 KiB
orq $0, (%rsp) ;Perform a useless RW operation to test if there is enough stack space for __stack_chk_fail
addq $4128, %rsp ;This leave 16 byte allocated for local vars
movq %rdi, %rdx ;See above
sarq $63, %rdx ;See above
movq %fs:40, %rax ;Get the canary
movq %rax, -8(%rbp) ;Save it as a local var
xorl %eax, %eax ;Clear it
movq %rdi, %rax ;See above
xorq %rdx, %rax ;See above
subq %rdx, %rax ;See above
movq -8(%rbp), %rcx ;RCX = Canary
xorq %fs:40, %rcx ;Check if equal to the original value
jne .L5 ;If not fail
leave
ret
.L5:
call __stack_chk_fail#PLT ;__stack_chk_fail is noreturn
So all the extra instructions are for implementing the Stack Smashing Protector.
Thanks to FUZxxl for pointing out the use of the first instructions after the prologue.
Many of the beginning calls are to setup the stack and save the return address (something which you are not doing). Seems like theres are some stack protection going on. Perhaps you could tune your compiler settings to get rid of some overhead.
Perhaps adding flags to you compiler such as: -fno-stack-protector could minimise this difference.
Yes this probably is slower than your handwritten assembly, but offers much more protection and is probably worth the slight overhead.
As for why the stack protection still exists even though it is a leaf function see here.
I'm trying to create a green thread implementation based off this tutorial, However my switch function is giving me a segfault because the code to load the registers is not run at the end of the function. Here is my code:
void ThreadSwitch(Thread in, Thread out) {
if (!out && !in) {
return;
}
if (out) {
// save registers for out
}
if (in) {
SetCurrentThread(in);
mtx_lock(&in->mutex);
uint64_t rsp = in->cpu.rsp;
uint64_t r15 = in->cpu.r15;
uint64_t r14 = in->cpu.r14;
uint64_t r13 = in->cpu.r13;
uint64_t r12 = in->cpu.r12;
uint64_t rbx = in->cpu.rbx;
uint64_t rbp = in->cpu.rbp;
mtx_unlock(&in->mutex);
asm volatile("mov %[rsp], %%rsp\n"
"mov %[r15], %%r15\n"
"mov %[r14], %%r14\n"
"mov %[r13], %%r13\n"
"mov %[r12], %%r12\n"
"mov %[rbx], %%rbx\n"
"mov %[rbp], %%rbp\n" : : [rsp] "r"(rsp), [r15] "r"(r15), [r14] "r"(r14), [r13] "r"(r13), [r12] "r"(r12), [rbx] "r"(rbx), [rbp] "r"(rbp));
}
}
Xcode says that the inline assembly is causing a segfault, but my lldb disassembly looks like this (you can ignore 95% of it, just provided for context):
0x1000f88b4: movq -0x8(%rbp), %rdi
0x1000f88b8: callq 0x1000f83a0 ; SetCurrentThread at thread.cc:21
0x1000f88bd: movq -0x8(%rbp), %rdi
0x1000f88c1: addq $0x50, %rdi
0x1000f88c8: callq 0x1000f7b80 ; mtx_lock at tct.c:106
0x1000f88cd: movq -0x8(%rbp), %rdi
0x1000f88d1: movq (%rdi), %rdi
0x1000f88d4: movq %rdi, -0x18(%rbp)
0x1000f88d8: movq -0x8(%rbp), %rdi
0x1000f88dc: movq 0x8(%rdi), %rdi
0x1000f88e0: movq %rdi, -0x20(%rbp)
0x1000f88e4: movq -0x8(%rbp), %rdi
0x1000f88e8: movq 0x10(%rdi), %rdi
0x1000f88ec: movq %rdi, -0x28(%rbp)
0x1000f88f0: movq -0x8(%rbp), %rdi
0x1000f88f4: movq 0x18(%rdi), %rdi
0x1000f88f8: movq %rdi, -0x30(%rbp)
0x1000f88fc: movq -0x8(%rbp), %rdi
0x1000f8900: movq 0x20(%rdi), %rdi
0x1000f8904: movq %rdi, -0x38(%rbp)
0x1000f8908: movq -0x8(%rbp), %rdi
0x1000f890c: movq 0x28(%rdi), %rdi
0x1000f8910: movq %rdi, -0x40(%rbp)
0x1000f8914: movq -0x8(%rbp), %rdi
0x1000f8918: movq 0x30(%rdi), %rdi
0x1000f891c: movq %rdi, -0x48(%rbp)
0x1000f8920: movq -0x8(%rbp), %rdi
0x1000f8924: addq $0x50, %rdi
0x1000f892b: movl %eax, -0x54(%rbp)
0x1000f892e: callq 0x1000f7de0 ; mtx_unlock at tct.c:264
0x1000f8933: movq -0x18(%rbp), %rdi ; beginning of inline asm
0x1000f8937: movq -0x20(%rbp), %rcx
0x1000f893b: movq -0x28(%rbp), %rdx
0x1000f893f: movq -0x30(%rbp), %rsi
0x1000f8943: movq -0x38(%rbp), %r8
0x1000f8947: movq -0x40(%rbp), %r9
0x1000f894b: movq -0x48(%rbp), %r10
0x1000f894f: movq %rdi, %rsp
0x1000f8952: movq %rcx, %r15
0x1000f8955: movq %rdx, %r14
0x1000f8958: movq %rsi, %r13
0x1000f895b: movq %r8, %r12
0x1000f895e: movq %r9, %rbx
0x1000f8961: movq %r10, %rbp ; end of inline asm
-> 0x1000f8964: movl %eax, -0x58(%rbp)
0x1000f8967: addq $0x60, %rsp
0x1000f896b: popq %rbp
0x1000f896c: retq
The segfault happens when it tries to access stuff back on the stack, which makes sense because it just switched out the stack. But why is the compiler inserting this? The compiler also stores %eax on the stack at 0x1000f892b. Is the compiler opening up a register? Because it doesn't use %rax in the inline asm. Is there a workaround?
This is using Apple LLVM version 6.0 (clang-600.0.57) on OSX 10.10.2, if that's any help.
Thanks in advance.
I strongly advise you not to write programs that depend on undefined behaviour.
Jumps into and out of inline assembly are not permitted as the compiler can't analyse control flow it doesn't know about, upon thread creation you jump into the asm statement from nowhere then leaves it. To avoid these implicit jumps you need to save and restore the registers including %rip in the same asm statement.
All registers that an asm statement alters must be listed as outputs or clobbers, for a thread switch routine that is all the registers whose values are not saved, as they are altered by the other threads. If you do not do so the compiler will incorrectly assume that they are not altered.
An asm statement must avoid overwriting it's inputs before they are used, in your code there is nothing prohibiting the compiler from storing the variable r12 in the register %r14.
Your lock is either pointless or inadequate.
It is much simpler to write your function entirely in assembly, like in tutorial you cite.
I am doing several experiments with x86 asm trying to see how common language constructs map into assembly. In my current experiment, I am trying to see specifically how C language pointers map to register-indirect addressing. I have written a fairly hello-world like pointer program:
#include <stdio.h>
int
main (void)
{
int value = 5;
int *int_val = &value;
printf ("The value we have is %d\n", *int_val);
return 0;
}
and compiled it to the following asm using: gcc -o pointer.s -fno-asynchronous-unwind-tables pointer.c:[1][2]
.file "pointer.c"
.section .rodata
.LC0:
.string "The value we have is %d\n"
.text
.globl main
.type main, #function
main:
;------- function prologue
pushq %rbp
movq %rsp, %rbp
;---------------------------------
subq $32, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
;----------------------------------
movl $5, -20(%rbp) ; This is where the value 5 is stored in `value` (automatic allocation)
;----------------------------------
leaq -20(%rbp), %rax ;; (GUESS) If I have understood correctly, this is where the address of `value` is
;; extracted, and stored into %rax
;----------------------------------
movq %rax, -16(%rbp) ;;
movq -16(%rbp), %rax ;; Why do I have two times the same instructions, with reversed operands???
;----------------------------------
movl (%rax), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
;----------------------------------
movl $0, %eax
movq -8(%rbp), %rdx
xorq %fs:40, %rdx
je .L3
call __stack_chk_fail
.L3:
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1"
.section .note.GNU-stack,"",#progbits
My issue is that I don't understand why it contains the instruction movq two times, with reversed operands. Could someone explain it to me?
[1]: I want to avoid having my asm code interspersed with cfi directives when I don't need them at all.
[2]: My environment is Ubuntu 14.10, gcc 4.9.1 (modified by ubuntu), and Gnu assembler (GNU Binutils for Ubuntu) 2.24.90.20141014, configured to target x86_64-linux-gnu
Maybe it will be clearer if you reorganize your blocks:
;----------------------------------
leaq -20(%rbp), %rax ; &value
movq %rax, -16(%rbp) ; int_val
;----------------------------------
movq -16(%rbp), %rax ; int_val
movl (%rax), %eax ; *int_val
movl %eax, %esi ; printf-argument
movl $.LC0, %edi ; printf-argument (format-string)
movl $0, %eax ; no floating-point numbers
call printf
;----------------------------------
The first block performs int *int_val = &value;, the second block performs printf .... Without optimization, the blocks are independent.
Since you're not doing any optimization, gcc creates very simple-minded code that does each statement in the program one at a time without looking at any other statement. So in your example, it stores a value into the variable int_val, and then the very next instruction reads that variable again as part of the next statement. In both cases, it is using %rax as the temporary to hold value, as that's the first register generally used for things.