Including header file in assembly file - gcc

I am trying to include a header file containing a macro into my main assembly file, but the compilation fails.
Below is my main.S file
#include "common.h"
BEGIN
mov $0x0E40, %ax
int $0x10
hlt
Below is my common.h file :
.macro BEGIN
LOCAL after_locals
.code16
cli
ljmp $0, $1f
1:
xor %ax, %ax
/* We must zero %ds for any data access. */
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %bp
/* Automatically disables interrupts until the end of the next instruction. */
mov %ax, %ss
/* We should set SP because BIOS calls may depend on that. TODO confirm. */
mov %bp, %sp
/* Store the initial dl to load stage 2 later on. */
mov %dl, initial_dl
jmp after_locals
initial_dl: .byte 0
after_locals:
.endm
Both files are in same directory. When I do the compilation :
$ as --32 -o main.o main.S
main.S: Assembler messages:
main.S:2: Error: no such instruction: `begin'
What am I missing? I did a little research and got this answer in SO, but its not helpful. Please help.

$ as --32 -o main.o main.S
as is just an assembler, it translates assembly source to object code. It does not run the C preprocessor which is supposed to expand #include.
(# is the comment character in GAS syntax for x86 so the line is treated as a comment if it's seen by the assembler instead of replaced by CPP)
What you can do:
Use gcc to assemble, with appropriate file suffix (.S or .sx), it will run the C preprocessor before running the assembler.
Add -v to see what commands gcc is invoking.
If your source has a different suffix, you can -x assembler-with-cpp source.asm.
If you want to see the intermediate result after preprocessing, add -save-temps. This will write a .s file with the preprocessed source.
If you want to pass down a command line option to as, you can for example -Wa,--32. However, it is better to use options which the compiler driver understands like -m32 or -m16 in the present case. The driver knows about such options, for example it will also cater for appropriate options when linking, provided you are linking with gcc -m32 ... as noted below.
Use a .include assembler directive which is handled by the assembler itself, not the C preprocessor.
Note: In case 1. adding include search paths by means of -I path might not work as expected: The compiler driver (gcc in this case) will add -I path only to the assembler's command line if it knows that it's the GNU assembler. You can tell this when the compiler is configured by configure flag --with-gnu-as.
Note: Similar applies to linking. You probably do not want to call the linker (ld by hand) unless you're making a static executable or flat binary; use gcc or g++ instead if you're making a normal executable to run on the host system. It will add many options needed for linking like multilib paths, search paths, etc. which you do not want to fiddle by hand.
(int $0x10 is a 16-bit BIOS call, though, which won't work under a modern mainstream OS, only DOS or a legacy BIOS bootloader.)

If your header file is just assembly then include with .include "file" directive in main.S. But this way of doing would insert the code the location where its included.

Related

Fix relocations for global variables in position-independent executables with GCC

I'm looking for a gcc command-line flag or other settings to produce GOTOFF relocations rather than GOT relocations for my statically linked, position-independent i386 executable. More details on what I was trying below.
My source file g1.s looks like this:
extern int answer;
int get_answer1() { return answer; }
My other source file g2.s looks like this:
extern int answer;
int get_answer2() { return answer; }
I compile them with gcc -m32 -fPIE -Os -static -S -ffreestanding -fomit-frame-pointer -fno-unwind-tables -fno-asynchronous-unwind-tables g1.c for i386.
I get the following assembly output:
.file "g1.c"
.text
.globl get_answer1
.type get_answer1, #function
get_answer1:
call __x86.get_pc_thunk.cx
addl $_GLOBAL_OFFSET_TABLE_, %ecx
movl answer#GOT(%ecx), %eax
movl (%eax), %eax
ret
.size get_answer1, .-get_answer1
.section .text.__x86.get_pc_thunk.cx,"axG",#progbits,__x86.get_pc_thunk.cx,comdat
.globl __x86.get_pc_thunk.cx
.hidden __x86.get_pc_thunk.cx
.type __x86.get_pc_thunk.cx, #function
__x86.get_pc_thunk.cx:
movl (%esp), %ecx
ret
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
.section .note.GNU-stack,"",#progbits
Here is how to reproduce this behavior online with GCC 7.2: https://godbolt.org/g/XXkxJh
Instead of GOT above, I'd like to get GOTOFF, and the movl %(eax), %eax should disappear, so the assembly code for the function should look like this:
get_answer1:
call __x86.get_pc_thunk.cx
addl $_GLOBAL_OFFSET_TABLE_, %ecx
movl answer#GOTOFF(%ecx), %eax
ret
I have verified that this GOTOFF assembly version is what works, and the GOT version doesn't work (because it has an extra pointer indirection).
How can I convince gcc to generate the GOTOFF version? I've tried various combinations of -fPIC, -fpic, -fPIE, -fpie, -pie, -fno-plt. None of them worked, all of them made gcc produce the GOT version.
I couldn't find any i386-specific flag on https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html or any generic flag here: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
In fact, I'm getting GOTOFF relocations for "..." string literals, and I also want to get them for extern variables.
The final output is a statically linked executable in a custom binary format (for which I've written a GNU ld linker script). There is no dynamic linking and no shared libraries. The address randomization is performed by a custom loader, which is free to load the executable to any address. So I do need position-independent code. There is no per-segment memory mapping: the entire executable is loaded as is, contiguously.
All the documentation I've been able to find online talk about position-independent executables which are dynamically linked, and I wasn't able to find anything useful there.
I wasn't able to solve this with gcc -fPIE, so I solved it manually, by processing the output file.
I use gcc -Wl,-q, with an output ELF executable file containing the relocations. I post-process this ELF executable file, and I add the following assembly instructions to the beginning:
call next
next:
pop ebx
add [ebx + R0 + (after_add - next)], ebx
add [ebx + R1 + (after_add - next)], ebx
add [ebx + R2 + (after_add - next)], ebx
...
after_add:
, where R0, R1, R2 ... are the addresses of R_386_32 relocations in the ELF executable. The In use objdump -O binary prog.elf prog.bin', and nowprog.bin' contains position-independent code, because it starts with the `add [ebx + ...], ebx' instructions, which do the necessary relocations to the code when the code starts running.
Depending on the execution environment, the gcc flag -Wl,-N is needed, to make the .text section writable (the `add [ebx + ...], ebx' instructions need that).

JS instruction - Hex code

I tried to cover asm to hex by gcc ( gcc -c -masm=intel code.s) by it error: code.s:1: Error: too many memory references for `mov'.
code.s asm:
mov rax , 0x00000000004007E6
js rax
what happened? Can you tutorial me cover it?
As Margaret Bloom said, -masm=intel is only a code generation option, meaning it affects what kind of assembly the compiler generates from C code. It does not affect assembling at all.
You need to put .intel_syntax noprefix directive in your assembly file to switch syntax, or use the convoluted gcc -Wa,--msyntax=intel,-mnaked-reg method to pass argument to the assembler.
Having done the above, the next issue will be that js rax is invalid as there is no conditional indirect jump in x86. The easiest will be probably to use a reversed condition, jns, to skip over a jmp rax.

How to set gcc or clang to use Intel syntax permanently for inline asm() statements?

I have the following code which compiles fine with the gcc command gcc ./example.c. The program itself calls the function "add_two" which simply adds two integers. To use the intel syntax within the extended assembly instructions I need to switch at first to intel and than back to AT&T. According to the gcc documentation it is possible to switch to intel syntax entirely by using gcc -masm=intel ./exmaple.
Whenever I try to compile it with the switch -masm=intel it won't compile and I don't understand why? I already tried to delete the instruction .intel_syntax but it still don't compile.
#include <stdio.h>
int add_two(int, int);
int main(){
int src = 3;
int dst = 5;
printf("summe = %d \n", add_two(src, dst));
return 0;
}
int add_two(int src, int dst){
int sum;
asm (
".intel_syntax;" //switch to intel syntax
"mov %0, %1;"
"add %0, %2;"
".att_syntax;" //switch to at&t syntax
: "=r" (sum) //output
: "r" (src), "r" (dst) //input
);
return sum;
}
The error message by compiling the above mentioned program with gcc -masm=intel ./example.c is:
tmp/ccEQGI4U.s: Assembler messages:
/tmp/ccEQGI4U.s:55: Error: junk `PTR [rbp-4]' after expression
/tmp/ccEQGI4U.s:55: Error: too many memory references for `mov'
/tmp/ccEQGI4U.s:56: Error: too many memory references for `mov'
Use -masm=intel and don't use any .att_syntax directives in your inline asm. This works with GCC and I think ICC, and with any constraints you use. Other methods don't. (See Can I use Intel syntax of x86 assembly with GCC? for a simple answer saying that; this answer explores exactly what goes wrong, including with clang 13 and earlier.)
That also works in clang 14 and later. (Which isn't released yet but the patch is part of current trunk; see https://reviews.llvm.org/D113707).
Clang 13 and earlier would always use AT&T syntax for inline asm, both in substituting operands and in assembling as op src, dst. But even worse, clang -masm=intel would do that even when taking the Intel side of an asm template using dialect-alternatives like asm ("add {att | intel}" : ... )`!
clang -masm=intel did still control how it printed asm after its built-in assembler turned an asm() statement into some internal representation of the instruction. e.g. Godbolt showing clang13 -masm=intel turning add %0, 1 as add dword ptr [1], eax, but clang trunk producing add eax, 1.
Some of the rest of this answer talking about clang hasn't been updated for this new clang patch.
Clang does support Intel-syntax inside MSVC-style asm-blocks, but that's terrible (no constraints so inputs / outputs have to go through memory.
If you were hard-coding register names with clang, -masm=intel would be usable (or the equivalent -mllvm --x86-asm-syntax=intel). But it chokes on mov %eax, 5 in Intel-syntax mode so you can't let %0 expand to an AT&T-syntax register name.
-masm=intel makes the compiler use .intel_syntax noprefix at the top of its asm output file, and use Intel-syntax when generating asm from C outside your inline-asm statement. Using .att_syntax at the bottom of your asm template breaks the compiler's asm, hence the error messages like PTR [rbp-4] looking like junk to the assembler (which is expecting AT&T syntax).
The "too many operands for mov" is because in AT&T syntax, mov eax, ebx is a mov from a memory operand (with symbol name eax) to a memory operand (with symbol name ebx)
Some people suggest using .intel_syntax noprefix and .att_syntax prefix around your asm template. That can sometimes work but it's problematic. And incompatible with the preferred method of -masm=intel.
Problems with the "sandwich" method:
When the compiler substitutes operands into your asm template, it will do so according to -masm=. This will always break for memory operands (the addressing-mode syntax is completely different).
It will also break with clang even for registers. Clang's built-in assembler does not accept %eax as a register name in Intel-syntax mode, and doesn't accept .intel_syntax prefix (as opposed to the noprefix that's usually used with Intel-syntax).
Consider this function:
int foo(int x) {
asm(".intel_syntax noprefix \n\t"
"add %0, 1 \n\t"
".att_syntax"
: "+r"(x)
);
return x;
}
It assembles as follows with GCC (Godbolt):
movl %edi, %eax
.intel_syntax noprefix
add %eax, 1 # AT&T register name in Intel syntax
.att_syntax
The sandwich method depends on GAS accepting %eax as a register name even in Intel-syntax mode. GAS from GNU Binutils does, but clang's built-in assembler doesn't.
On a Mac, even using real GCC the asm output has to assemble with an as that's based on clang, not GNU Binutils.
Using clang on that source code complains:
<source>:2:35: error: unknown token in expression
asm(".intel_syntax noprefix \n\t"
^
<inline asm>:2:6: note: instantiated into assembly here
add %eax, 1
^
(The first line of the error message didn't handle the multi-line string literal very well. If you use ; instead of \n\t and put everything on one line the clang error message works better but the source is a mess.)
I didn't check what happens with "ri" constraints when the compiler picks an immediate; it will still decorate it with $ but IDK if GAS silently ignores that, too, in Intel syntax mode.
PS: your asm statement has a bug: you forgot an early-clobber on your output operand so nothing is stopping the compiler from picking the same register for the %0 output and the %2 input that you don't read until the 2nd instruction. Then mov will destroy an input.
But using mov as the first or last instruction of an asm-template is usually also a missed-optimization bug. In this case you can and should just use lea %0, [%1 + %2] to let the compiler add with the result written to a 3rd register, non-destructively. Or just wrap the add instruction (using a "+r" operand and an "r", and let the compiler worry about data movement.) If it had to load the value from memory anyway, it can put it in the right register so no mov is needed.
PS: it's possible to write inline asm that works with -masm=intel or att, using GNU C inline asm dialect alternatives. e.g.
void atomic_inc(int *p) {
asm( "lock add{l $1, %0 | %0, 1}"
: "+m" (*p)
:: "memory"
);
}
compiles with gcc -O2 (-masm=att is the default) to
atomic_inc(int*):
lock addl $1, (%rdi)
ret
Or with -masm=intel to:
atomic_inc(int*):
lock add DWORD PTR [rdi], 1
ret
Notice that the l suffix is required for AT&T, and the dword ptr is required for intel, because memory, immediate doesn't imply an operand-size. And that the compiler filled in valid addressing-mode syntax for both cases.
This works with clang, but only the AT&T version ever gets used.
Note that -masm= also affects the default inline assembler syntax:
Output assembly instructions using selected dialect. Also affects
which dialect is used for basic "asm" and extended "asm". Supported
choices (in dialect order) are att or intel. The default is att.
Darwin does not support intel.
That means that your first .intel_syntax directive is superfluous and the final .att_syntax is wrong because your GCC call compiles C to Intel assembler code.
IOW, either stick to -masm=intel or sandwich your inline Intel assembler code sections between .intel_syntax noprefix and .att_syntax prefix directives - but don't do both.
Note that the sandwich method isn't compatible with all inline assembler constraints - e.g. a constraint that involves m (i.e. memory operand) would insert an operand in ATT syntax which would yield an error like 'Error: junk (%rbp) after expression'. In those cases you have to use -masm=intel.

How to link 32-bit Nasm assembly object code on a 64-bit windows computer

I found the following code from http://www.dreamincode.net/forums/topic/328714-my-program-keeps-crashing/.
global start
;~ msvcrt.dll
extern _printf
%define printf _printf
;~ kernel32.dll
extern ExitProcess, GetCommandLineW, LocalFree
%define GetCommandLine GetCommandLineW
;~ shell32.dll
extern CommandLineToArgvW
%define CommandLineToArgv CommandLineToArgvW
SECTION .data
message db 'Hello, World', 13, 10, 0
fmtstr db "%s", 0
fmtstrCL db "Arg","%d", " = ", "%S", 13, 10, 0
section .bss
pNumArgs resd 1
section .text
start:
call GetCommandLine
push pNumArgs
push eax
call CommandLineToArgv
mov esi, eax
mov ebx, [pNumArgs]
DisplayArgs:
dec ebx
push dword[esi + 4 * ebx]
inc ebx
push ebx
push fmtstrCL
call printf
add esp, 4 * 3
dec ebx
jnz DisplayArgs
push esi
call LocalFree
push message ; Push address of "Hello, world!" onto the stack
push fmtstr ; push address of formatter onto the stack
call printf ; Print the message
add esp, 4 * 2 ; adjust stack pointer
push 0
call ExitProcess
My goal is to learn assembly language by reading other people's code and eventually write my own. I cannot figure out how to link 32-bit assembly programs on my 64-bit windows computer.
To assemble the program I use the command:
nasm -f win32 hello32.asm -o hello32.o
To link the object file I use:
gcc hello32.o -o hello32.exe
After I issue the link command I get the following error:
C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: i386 arc
hitecture of input file `hello32.o' is incompatible with i386:x86-64 output
hello32.o:hello32.asm:(.text+0x24): undefined reference to `_printf'
hello32.o:hello32.asm:(.text+0x3f): undefined reference to `_printf'
C:/Program Files/mingw-w64/x86_64-5.2.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/
gcc/x86_64-w64-mingw32/5.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw3
2.a(lib64_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined refere
nce to `WinMain'
collect2.exe: error: ld returned 1 exit status
I am using 64-bit mingw binaries that are supposed to be compatible with making 32-bit programs. I have tried switching to 32-bit mingw binaries and I get a massive amount of undefined reference errors. I can link simple skeleton files without any problems using the above commands. I have no idea what I am doing wrong and I would appreciate any guidance someone could give me.
i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output
NASM has created a 32 bit object file, but you are trying to link a 64 bit executable. You could try to use the -m32 switch to create a 32 bit executable, but you already found out that this causes another bunch of errors. I do not have a solution for that either.
To link your executable, use a 32 bit MingW environment. I tried MinGW4.6.2 32 bit which worked well.
Alternatively, you can use the linker (link.exe) from a Microsoft Visual Studio installation.
https://github.com/afester/CodeSamples/tree/master/Asm/nasm_win32 shows a hello world example together with a Makefile which uses the Visual Studio linker. Alternatively, using gcc helloworld.obj -o hello32.exe from a MingW32 installation works also.
Two issues:
You're using the option -f win32 but asking for the object file in *.o extension. The two formats, .o and .obj are not compatible. But of course, you're free to specify your own extension, and so nasm will obediently assemble your code into a file with i386 arc format .o file.
Next, you're asking gcc to build that hello32.exe, using the file hello32.o. Effectively, you gave gcc an arc format .o file, and asked to build a 64-bit PE format executable out of it. And then (naturally) gcc complains:
i386 architecture of input file `hello32.o' is incompatible with i386:x86-64 output
which is correct.
Two ways you can fix this:
Assemble with: nasm -fwin32 hello32.asm and then, link with gcc -m32 hello32.obj -o hello32.exe
Assemble with: nasm -fobj hello32.asm and then link with alink -subsys console -oPE hello32.o. You can get alink from here.
Let me know which worked for you.
P.S. I have outlined the problems I have faced myself in this blog, hope that helps.

GNU assembler did not produce a program that I can execute

I tried assembling some intermediate code generated by gcc. I used the command as -o hello hello.s, which, as far as I can tell, is the correct syntax. When I tried to run the program, it said bash: ./hello: cannot execute binary file. It doesn't seem like there's a problem with the assembly code, since it was the code generated by gcc, and it doesn't seem like there's anything wrong with how I invoked the assembler, since that seems to be the right syntax according to this manual. Can anyone help me with this?
Working with GNU Assembler
Assume that your assembly file is called hello.s and looks something like (assuming a 32-Bit Linux target):
.data
msg: .asciz "Hello World\n"
msglen = .-msg
.text
.global _start
_start:
/* Use int $0x80/eax=4 to write to STDOUT */
/* Output Hello World */
mov $4, %eax /* write system call */
mov $0, %ebx /* File descriptor 0 = STDOUT */
mov $msg, %ecx /* The message to output */
mov $msglen, %edx /* length of message */
int $0x80 /* make the system call */
/* Exit the program with int $0x80/eax=1 */
mov $1, %eax /* 1 = exit system call */
mov $0, %ebx /* value to exit with */
int $0x80 /* make the system call */
This is a 32-bit Linux assembler program in AT&T syntax that displays Hello World to standard output using 32-bit system calls via int $0x80. It doesn't use any C functions so can be assembled with the GNU assembler as and linked with the GNU linker ld to produce a final executable.
as --32 hello.s -o hello.o
ld -melf_i386 hello.o -o hello
The first line assembles hello.s into a 32-bit ELF object called hello.o . hello.o is then linked to a 32-bit ELF executable called hello with the second command. The GNU linker assumes by default that your program starts execution at the label _start .
Alternatively you can use GCC to assemble and link this program with this command:
gcc -nostdlib -m32 hello.s -o hello
This will produce a 32-bit ELF executable called hello . The -nostdlib tells GCC not to link in the C runtime library and allows us to use _start as our program's entry point.
If your assembler program is intended to be linked to the C runtime and library so that it can utilize functions like C's printf then things are a bit different. Assume you have this program that needs printf (or any of the C library functions):
.data
msg: .asciz "Hello World\n"
.text
.global main
main:
push %ebp /* Setup the stack frame */
mov %esp, %ebp /* Stack frames make GDB debugging easier */
push $msg /* Message to print */
call printf
add $4,%esp /* cleanup the stack */
xor %eax, %eax /* Return 0 when exiting */
mov %ebp, %esp /* destroy our stack frame */
pop %ebp
ret /* Return to C runtime that called us
and allow it to do program termination */
Your entry point now must be mainon most *nix type systems. The reason is that the C runtime will have an entry point called _start that does C runtime initialization and then makes a call to the function called main which we supply in our assembler code. To compile/assemble and link this we can use:
gcc -m32 hello.s -o hello
Note: on Windows the entry point called by the C runtime is _WinMain, not main.
Working with NASM
In the comments you also asked about NASM so I'll provide some information when assembling with it. Assume that your assembly file is called hello.asm and looks something like (It doesn't require the C runtime libraries):
SECTION .data ; data section
msg db "Hello World", 13, 10
len equ $-msg
SECTION .text ; code section
global _start ; make label available to linker
_start: ; standard gcc entry point
mov edx,len ; length of string to print
mov ecx,msg ; pointer to string
mov ebx,1 ; write to STDOUT (file descriptor 0)
mov eax,4 ; write command
int 0x80 ; interrupt 80 hex, call kernel
mov ebx,0 ; exit code, 0=normal
mov eax,1 ; exit command to kernel
int 0x80 ; interrupt 80 hex, call kernel
Then to build it into an executable you can use commands like these:
nasm -f elf32 hello.asm -o hello.o
gcc -nostdlib -m32 hello.o -o hello
The first command assembles hello.asm to the ELF object file hello.o . The second line does the linking. -nostdlib excludes the C runtime from be linked in (functions like _printf etc wouldn't be available). The second line links hello.o to the executable hello .
Alternatively you can skip using GCC and use the linker directly like this:
nasm -f elf32 hello.asm -o hello.o
ld -melf_i386 hello.o -o hello
If you need the C runtime and library for calling things like printf then it is a bit different. Assume you have this NASM code that needs printf:
extern printf
SECTION .data ; Data section, initialized variables
msg: db "Hello World", 13, 10, 0
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
push ebp ; Setup the stack frame
mov ebp, esp ; Stack frames make GDB debugging easier
push msg ; Message to print
call printf
add esp, 4 ; Cleanup the stack
mov eax, 0 ; Return value of 0
mov esp, ebp ; Destroy our stack frame
pop ebp
endit:
ret ; Return to C runtime that called us
; and allow it to do program termination
Then to build it into an executable you can use commands like these:
nasm -f elf32 hello.asm -o hello.o
gcc -m32 hello.o -o hello
Neither a compiler nor an assembler generates an executable file. Both generate an object file, which can then be linked with other object and/or library files to generate an executable.
The command gcc -c, for example, invokes just the compiler; it can take a source file like hello.c as input and generate an object file like hello.o as output.
Likewise, as can take an assembly language source file like hello.s and generate an object file like hello.o.
The linker is a separate tool that generates executables from object files.
It just happens that compiling and linking in one step is so convenient that that's what the gcc command does by default; gcc hello.c -o hello invokes the compiler and the linker to generate an executable file.
Note that the gcc command isn't just a compiler. It's a driver program that invokes the preprocessor, the compiler proper, the assembler, and/or the linker. (The preprocessor and assembler, can be thought of as components of the compiler, and in some cases they aren't even separate programs, or a compiler can generate machine object code instead of assembly code.)
In fact, you can perform the same multi-step process in one command for assembly language as well:
gcc hello.s -o hello
will invoke the assembler and linker and generate an executable file.
This is specific to gcc (and probably to most other compilers for Unix-like systems). Other implementations might be organized differently.

Resources