Eclipse Oxygen and NASM assembler

I had been playing about with assembler after many years of missing it and decided to try and find an IDE that works with using a C/C++ project with assembler code.

Well, I found one.

Eclipse Oxygen (may work with earlier versions too)

  1. Create a new C project. You can do this with C++ projects too if you remember to use extern “C”.

You will get a default project file like this:

/*
 ============================================================================
 Name        : testasm.c
 Author      : WLGfx
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include 
#include 

int main(void) {
	puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
	return EXIT_SUCCESS;
}

2. Set up NASM for 64 bit using Project->Properties->Settings->GCC Assembler

Change ‘as’ to ‘nasm’. That is only if you already have installed NASM.

3. Set NASM to build for 64 bit.

From the screenshot showing the change from ‘as’ to ‘nasm’, now click on ‘General’ just under ‘GCC Assembler’. Now in the ‘Assembler flags’ you just add ‘-f elf64’ and click ‘Apply’. That’s the assembler setup to use the intel syntax in Eclipse.

4. Create a new file called ‘test.asm’ and copy the code below into it. If you’re in the C/C++ perspective view in eclipse you have to go round the houses to create an empty file. ie. File->New->Other->General->File and finally you are there.

EDIT: Actually, if you right click on the ‘src’ folder then you can add a blank file from there.

You now have an assembler file, empty, but it’s there.

Don’t worry at this point about things getting complicated, because Eclipse still handles the build and linking of these assembler files automatically.

Copy this code into that empty file:

; random number generator to be used in crypto transmission
; of sensitive data over the internet

; WLGfx 2017-Nov-19

        section .text

global  _testmain:function

extern  printf

srand:  mov     [seed],rax                      ; set random seed
        ret

arand:  mov     rax,[seed]                      ; get seed
        mov     rbx,qword 0x023defca321acfed
        add     rax,rbx                         ; add 64 bit value
        rol     rax,19                          ; rotate bits
        mov     rbx,qword 0xbead6789
        add     rax,rbx                         ; another add
        imul    rax,qword 0x1234567c            ; a multiple this time
        mov     rbx,rax                         ; copy into rbx
        xor     rax,qword 0x5ecdab73            ; flip some bits
        rol     rax,48                          ; rotate bits again
        mov     rcx,rax                         ; copy to rcx
        and     rax,0x3                         ; mask and test with 0
        jnz     .notz                           ; 25% chance of other ops
        mov     rax,rbx
        add     rcx,rax
        mov     rbx,qword 0x87650027
        imul    rax,rbx
        jmp     .cont
.notz   mov     rax,rcx                         ; back into rax
.cont   mov     [seed],rax                      ; store into seed
        and     rax,0xff                        ; return byte value only
        ret

_testmain:
		mov     rax,9                           ; set seed
        call    srand

        mov     dword[lc],10                    ; set loop counter

.loop   call    arand                           ; get random byte

        push    rbp                             ; stack frame
        mov     rsi,rax                         ; random number
        mov     rdi,pf_msg                      ; format string
        xor     rax,rax                         ; 0
        call    printf                          ; call printf
        pop     rbp                             ; stack frame

        sub     dword[lc],1                     ; dec loop counter
        jnz     .loop

        ret

        section .data

seed    dq      0,0,0,0                         ; random seed value 64 bit
lc      dd      10                              ; loop counter

pf_msg  db      "Number: 0x%02x",10,0

In the above code I’ve declared and external function as you can see. Fortunately the underscore is still seen from C so the function name stays the same as you will see. I’m using the underscores as a note to myself that I am calling an assembler function. In future I will use a double underscore so that it doesn’t pollute other names withing the C/C++ libraries and headers.

5.  Change your C file to this:

#include 
#include 

_testmain();

int main(void) {
	puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */

	_testmain();

	return EXIT_SUCCESS;
}

6. Build and Run and you get the output (if you’re on 64 bit)

!!!Hello World!!!
Number: 0xe0
Number: 0x5b
Number: 0xca
Number: 0x7c
Number: 0xfc
Number: 0x2d
Number: 0x79
Number: 0xa5
Number: 0x62
Number: 0x7f

7. Enjoy because I am now…