Question about assembly - syntax

.text
.globl main
main:
xorl %eax,%eax ;return 0
ret
Like such a tiny programe:
1.is it true that indentation is just personal preference?
2.the complete of assembly is of various .tags and func:, is there any other part missing that can no be included in these two categories?

Yes, I do think indentation is just to make it easy for you and other people to read your program.
"func : " are labels which act as a way of helping you reference difference parts of your program. It helps a lot when doing loops and such.
".tags" or ".globl" are directives, these are used by the assembler when assembling your code to machine instructions.

Related

Where does an “ADD” instruction store the result? [duplicate]

MOV is probably the first instruction everyone learns while learning ASM.
Just now I encountered a book Assembly Language Programming in GNU/Linux for IA32 Architectures By Rajat Moona which says: (broken link removed)
But I learnt that it is MOV dest, src. Its like "Load dest with src". Even Wiki says the same.
I'm not saying that the author is wrong. I know that he is right. But what am I missing here?
btw.. he is using GCC's as to assemble these instructions. But that shouldn't change the instruction syntax right?
mov dest, src is called Intel syntax. (e.g. mov eax, 123)
mov src, dest is called AT&T syntax. (e.g. mov $123, %eax)
UNIX assemblers including the GNU assembler uses AT&T syntax, all other x86 assemblers I know of uses Intel syntax. You can read up on the differences on wikipedia.
Yes, as/gas use AT&T syntax that uses the order src,dest. MASM, TASM, NASM, etc. all use the order 'dest, src". As it happens, AT&T syntax doesn't fit very well with Intel processors, and (at least IMO) is a nearly unreadable mess. E.g. movzx comes out particularly bad.
There are two distinct types of assembly language syntax - Intel and AT&T syntax.
You can find a comparison of both on Wikipedia's assembly language page.
Chances are your book uses the AT&T syntax, where the source operand comes before the destination.
As already mentioned in the answer by Jerry Coffin, the Intel syntax fits better with the encoding of instructions for the x86 architecture. As a comment in my debugger's disassembler states, "the operands appear in the instruction in the same order as they appear in the disassembly output". For example, consider this instruction:
-a
1772:0100 test word [AA55], 1234
1772:0106
-u 100 l 1
1772:0100 F70655AA3412 test word [AA55], 1234
-
As you can read in the opcode hexdump, the instruction opcode 0F7h is first, then the ModR/M byte 06h, then the little-endian offset word 0AA55h, and then finally the immediate word 1234h. The Intel syntax matches that order in the assembly source. In the AT&T syntax this would look like testw $0x1234, (0xAA55) which swaps the order compared to the encoding.
Another example that obeys the Intel syntax order is comparison conditions. For example, consider this sequence:
cmp ax, 26
jae .label
This will jump to .label if ax is above-or-equal-to 26 (in unsigned comparison). This mnemonic is only true of the cmp dest, src operand order, which sets flags as for dest -= src.

What does this backslash do in this assembly code?

I am not sure what the difference is in these push lines. (trimmed down from Linux's x86/entry/calling.h, with the xor-zero clearing removed.)
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
pushq \rdx
pushq \rax
pushq %r11
pushq %r12
.endm
Do both push onto the stack? Or do the first two push lines do something different? I am on linux using the GNU toolchain.
These lines where found in a .h file that's included by .S asm source files.
Also can anyone tell me what this code does?
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
Specifically the code after PUSH_AND_CLEAR_REGS.
Inside a GAS .macro, you use \foo to refer to a macro parameter called foo.
The .macro you're looking at has 3 args with default values; presumably in some use-case they want to get alternate values saved in place of what's actually in RAX and RDX. But the rest of the registers get saved and xor-zeroed as normal.
So after macro expansion, yes it's just push %rdx and push %rax, same as the push %r11 and push %r12.
IDK if you were looking at an old version of Linux, but this is in a .h that's included by other .S hand-written asm source files, not by .c sources. I fixed your question for you.
I thought the comment on the GAS macro definition was was pretty clear about the purpose of this macro. See the github link I added to your question.

Assembly ".set" directive emitting symbol

In some kernel-mode assembly source I have a line that looks like this:
; excerpt #1
.set __framesize, ROUND_TO_STACK(localvarsize)
(localvarsize is a parameter to a C-preprocessor macro, if you’re wondering.) I assume that __framesize is a compile-time variable that is usable in .if statements, and is then discarded. However, I find references to a symbol named __framesize in the symbol table and disassembly of my kernel. The symbol is defined (as output by nm -m) as such:
; excerpt #2
0000000000000000 (absolute) non-external __framesize
The usage of __framesize in compiler-generated assembly is as such:
; excerpt #3
movq %gs:__framesize, %rax
movq 0x140(%rax), %r15
Given what I understand of my compiler and my kernel, excerpt #3 should be emitted as movq %gs:0x140, %r15, and that code should work. (The code that is actually being emitted from the C as excerpt #3 is causing a triple fault on the second line.)
I have two questions:
Should this __framesize symbol be emitted into my binary by the assembler when used in this fashion? If possible, how can I suppress it?
Would this usage of __framesize cause a problem like what is discussed above?
I am using GAS assembler syntax and the Xcode 7.1.1 assembler, and a Mach-O output format, if it is useful.
The GNU as manual says that .set modifies the value(i.e. address) and/or type of an existing symbol. It's synonymous with .equ, so it can be used to set/modify assembler macro variable, or to mess around with symbols which are also labels.
If __framesize is showing up in the object file, then it's probably declared somewhere else.
Try looking at the disassembly output, to see what really happened.

Doesn't PIC mean no relocations?

I'm building an ELF SO for bada on ARM using GCC. The compiler options include -fpic. Yet in the built file, when I do readelf -r, there's a whole lot of relocation records, of following types:
R_ARM_RELATIVE
R_ARM_REL32
R_ARM_ABS32
R_ARM_GLOB_DAT
R_ARM_JUMP_SLOT
What am I misunderstanding here?
EDIT: from what I can see, the PIC implementation in the compiler doesn't use GOT. Instead, they use PC-relative addressing with stored constants being offsets from point of use to the symbol address; that's resolved by the linker. Like this, to read a global variable:
ldr r12, OffsetToVar
PointOfUse:
ldr r0, [r12, pc]
# r0 now has the value of MyVar
#...
# At function's end...
OffsetToVar:
.long MyVar-PointOfUse-8
# Compiler can't resolve this, since it doesn't know
# the address of MyVar, but linker can
Similar idea for cross-module function calls. When a project mixes ARM and Thumb code though, the latter may misfire. But I've worked around that.
Doesn't PIC mean no relocations?
No, it does not.
It just means no relocations against .text section (so the .text can be shared between multiple processes).

Inline assembly __sync_fetch_and_add and __sync_add_and_fetch

The GCC builtin __sync_fetch_and_add is an implementation of the x86 inline assembly:
asm("lock; xaddl %%eax, %2;"
:"=a" (val)
: "a" (val), "m" (*ptr) : )
How can I implement this inline assembly using the addl instruction instead of xaddl?
And another question that I have is how would be the x86 inline assembly of the builtin __sync_add_and_fetch ?
Thanks.
Builtins do not necessarily correspond with a single well defined chunk of assembly code. In particular both __sync_add_and_fetch and __sync_fetch_and_add will generate lock addl instead of lock xaddl if the result is not live out of the builtin, and they may generate lock incl if the result is not live out and the second argument is known to have the value 1.
It is not clear what you mean by "how can I implement this inline assembly". Assembly is something that you write or generate, not something that you implement (unless you are writing an assembler).

Resources