Inline ASM in G++ (Eclipse)

Hello. I want to test my basic knowledge of ASM with a simple add(a, b) function, that adds a and b using assembly. I have never been able to use inline ASM, because I couldn't figure out how. Can someone direct me to a very, VERY basic tutorial of inline ASM? I'm sure I'm leaving out some major detail as to what my operating system is or whatever. If that is important, please explain why in simple terms. Thanks.

P.S. Sorry if I am asking too much.
inline asm depends on the platform how the syntax works -- visual studio vs g++ are rather different, and I am assuming an X86 processor family here?

https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

it is rarely useful to do more than 5 or so operations at a go. Most of the speedups you can do with it these days are to force the machine to do something simple that is not supported in c++ because its not on every chip, for example x86 has an endian reverse command that not all CPU have which is much faster than shuffling bytes around.

you probably want to either let C++ handle the function part (you can do the innards) or be very careful with the calling conventions stuff.
Last edited on
It's not like there's no information on the web.
https://duckduckgo.com/?q=Inline+ASM+in+G%2B%2B

Seriously, if you want to program in asm, you need to up your game.
This will be so much harder than programming in the higher level languages. If you don't have the grit to dig into problems hard, it's not going to work out. Assembly does not take prisoners!.

Like showing which sites you've studied, what you've tried, what results (or lack thereof) you've seen.

Also write very small functions in C, compile with the -S flag and study the results.
This can be an education in itself.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ gcc -S foo.c
$ cat foo.c foo.s
int add ( int a, int b ) {
  return a + b;
}

	.file	"foo.c"
	.text
	.globl	add
	.type	add, @function
add:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	%edi, -4(%rbp)
	movl	%esi, -8(%rbp)
	movl	-4(%rbp), %edx
	movl	-8(%rbp), %eax
	addl	%edx, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	add, .-add
	.section	.note.GNU-stack,"",@progbits


Adding -O2 to the compile line reduces the heart of the generated code to this:

1
2
	leal	(%rdi,%rsi), %eax
	ret

It takes advantage of the "load effective address" instruction and the fact that the parameters are passed in rdi and rsi and the return value is meant to be in eax.
Thanks, everyone. I will study your answers more thoroughly and see what I can learn.

@salem c: I have tried searching on the web, but the fact that I don't know much about
processors and such made it a little hard for me to understand what syntax to use and
what-not. Thanks for making me aware of the obvious lack of research in my post. I am
going to do some research before I ask more questions on the subject.
Last edited on
Thanks. I have made this function:
1
2
3
4
5
6
7
8
int increment(int a) {
	int result, increment = 1;
	
	__asm__("addl %%ebx, %%eax"
		: "=a" (result)
		: "a" (a), "b" (increment));
	return result;
}


I don't know whether it is the best way to do this or not, but it works. :D
I don't understand the "=a", "a" and "b" parts yet, but I'll keep learning.
g++ asm syntax is funky. it won't let you directly use the c++ variables, you have to have those extra bits to connect them.
Ah, alright. I've noticed that if I change %%eax to %%edx, it only works if I change "=a" to "=d" and "a" to "d". I partly understand that, actually. It is saying that the output of eax + ebx (a + b) will be stored in eax (a). Thus, the output of edx + ebx (d + b, not a + b) will be stored in edx (d). If this is true, how many e*x registers are there? And do I always use the middle letter?
you will need to start reading an x86 manual.
it does not work that way. some registers cannot be added together, and the result is often the A register.
A,B,C,D are the main registers. al and ah are 8 bit, ax and bx etc are 16 bit, eax ecx etc are 32 bit, and rax, rbx, etc are 64 bit. al is part of ax is part of eax is part of rax .. they are not distinct things but a way to slice up the same 64 bit circuits.

some are used more for indexing/memory, ax and bx are used more for computation, ax tends to be the result, ... instructions have specific targets and side effects that you need to be aware of them. In some ways registers are like global variables and you need to trace carefully what functions use which ones and how.
Alright. Sorry for taking up so much time. Do you know of a good, up-to-date x86 manual?
Note that with VS, you can't do 64bit build in-line assembler - you can only do this with 32 bit build. Don't know about G++.

Have a look at this book Low-Level Programming: C, Assembly, and Program Execution on IntelĀ® 64 Architecture https://www.amazon.co.uk/Low-Level-Programming-Assembly-Execution-Architecture/dp/1484224027/ref=sr_1_1?dchild=1&keywords=low+level+programming&qid=1624010149&s=books&sr=1-1
Last edited on
Alright. Thank you! I don't really use VS anymore, I generally use Eclipse now. I'll take a look at that page. Thanks.
Last edited on
Topic archived. No new replies allowed.