10

have been following an assembly tutorial on youtube here through AT&T syntax. I have just learned about declaring(if that's the correct term here) a function with the .type directive, such as:

.type MyFunction, @function

Now I can define my function like:

MyFunction:
    <code here>

And subsequently call it whenever:

call MyFunction

I know that previous to this in the tutorials, we were simply creating a label that was attached to some code:

MyLabel:
    <code here>

which could then be called like this:

call MyLabel

So my questions are:

What exactly is the difference between a function declared with .type, and and 'function' declared simply with a label? When should one be used over the other, or does it matter?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
user3118363
  • 337
  • 4
  • 13
  • 2
    Labels are often used for branch targets. Functions are 'exported' in the object file, and resolved by the linker - so it can be called from another object. Since you mention AT&T, I assume you are learning x86[-64] on Linux/BSD (or OSX)? – Brett Hale Jul 14 '15 at 11:59
  • 1
    Yes I'm learning on x86_64 linux – user3118363 Jul 14 '15 at 12:15
  • 4
    AT&T with [GNU as](https://sourceware.org/binutils/docs-2.25/as/index.html) (gas) isn't very user friendly, but you don't need many directives to write simple functions, and you can refer to assembly output from gcc to look at how simple C functions translate. You might consider [nasm](http://www.nasm.us/) if you're more comfortable with [Intel syntax](https://en.wikipedia.org/wiki/X86_assembly_language#Syntax). There's also the [ELF ABI](http://www.x86-64.org/documentation_folder/abi-0.99.pdf) which explains calling conventions and stack frames for x86-64 Linux. – Brett Hale Jul 14 '15 at 13:23
  • and you are using gnu assembler or something else? – old_timer Jul 14 '15 at 14:57

3 Answers3

4

Here's what the binutils docs say about the .type directive (assuming you are using the GNU assembler):

This directive is used to set the type of a symbol.

...

For ELF targets, the .type directive is used like this:

.type name , type description

According to the docs on Symbol Type:

The type attribute of a symbol contains relocation (section) information, any flag settings indicating that a symbol is external, and (optionally), other information for linkers and debuggers. The exact format depends on the object-code output format in use.

.type MyFunction, @function marks the label MyFunction (which is a symbol) as a function for the linker or debugger.

When writing pure assembly files by hand, this is unnecessary. Here's an example of a file in which an itoa function is called. As you can see, there are no directives preceding the label.

In summary, labels can be marked as functions, but to executing code, it's just a jump target either way.

Community
  • 1
  • 1
General Grievance
  • 4,555
  • 31
  • 31
  • 45
2

As far as the CPU is concerned, there is no difference. Many assemblers don't require you to declare .type MyFunction, @function at all; rather, you just put MyFunction wherever you want and then call MyFunction to go there.

Labels are a feature of assemblers that makes them much better to use than what people did before they existed (i.e. putting in the bytes with a hex editor.) A code label like

MyFunction:
nop
ret

is effectively a constant pointer to the instruction directly below it, in this case the nop. Based on how much code is in your file, and where it is, the label MyFunction equals some number, but it's much easier to let the assembler manage that for us.

Imagine if we had no labels. We'd have to remember what address MyFunction is at, and every time we change our program we'd have to manually update all the jmp and call statements with the correct destination. Sounds terrible, doesn't it?

Relative branches are handled differently, but the end result is the same. For something like this:

MyFunction:
add eax,ebx
jne MyFunction

The MyFunction in jne MyFunction isn't encoded as a constant address, but is a signed offset that gets added to/subtracted from %rip in order to make it equal to whatever the memory location corresponding to MyFunction is.

EDIT: On x86 jmp and call are also relative as in the above example, but this is not the case for all architectures.

puppydrum64
  • 1,598
  • 2
  • 15
  • 1
    x86 `call` to a label/symbol uses a relative encoding. ([Why do x86 jump/call instructions use relative displacements instead of absolute destinations?](https://stackoverflow.com/q/46184755)) There is no absolute direct near `call` in x86 machine code (https://www.felixcloutier.com/x86/call). So in fact, call is the same as `jne` or `jmp`, except it doesn't have the option of a short `rel8` displacement, only `rel32`. Some other ISAs use absolute addresses for some forms of jump or call, or like MIPS `j` / `jal` are absolute within the same 256MiB segment (replacing the low 28 bits of PC). – Peter Cordes Dec 08 '22 at 16:16
  • My bad, I'm thinking of Z80 where `CALL` is always absolute. – puppydrum64 Dec 08 '22 at 16:19
  • 1
    Yeah, I think it's not rare for 8-bit ISAs to have absolute call/jump. Relocatable / position-independent code wasn't a big thing on such early machines, and an address is 2 bytes either way if you want to reach anywhere in the address space. – Peter Cordes Dec 08 '22 at 16:26
-1

I think whatever assembly you use the point is the return command. Whatever name for "return" in you assembler is used. Calling a function differs from branching in the fact that some context data (status register with N, C, V bits, program counter) are pushed/stored into stack. When the return command is executed the data from stack are restored. It is needed for ability to remain program execution from the address just after your function call.

Shkodzer
  • 69
  • 4
  • 2
    A normal function call doesn't save the flags, just the return. I believe you're thinking of an IRQ. – puppydrum64 Dec 08 '22 at 16:02
  • 1
    I mean other than that you're not wrong, if you `CALL` some label it better end in `RET` eventually if you want to actually return. – puppydrum64 Dec 08 '22 at 16:32