LABOUCHERE SYSTEM PROGRAM USING x86-64 REGISTERS


LABOUCHERE SYSTEM C PROGRAM  |  x86-64 TUTORIAL: HILBERT MATRIX

This program does not use any fixed memory locations for the head or tail of the link list, but uses all the registers available to it. However, for some of the functions it does not follow the convention of saving all the registers RBX, R12-R15 on the stack at every function call since some of these registers contain pointers to the head and tail of the link list. Even if we did that, the program would hardly change much.

Most of the code is the same as in the previous post, except for the replacement of the head and tail of the linked list with registers R12 and R13.


section .rodata

    int_format0 db "WIN: %ld ",10,0
    int_format1 db "loss: %ld ",10,0
    int_format2 db "AMT: %ld ",10,0
    prompt1 db "RESULTS: %ld out of %ld tries",10,0

; struct Link {
;   int data;   
;   struct Link* prev;
;   struct Link* next;
;   };

%define data_offset     0
%define prev_offset     8
%define next_offset     16
%define size_of_list    24

%define RAND_MAX        2147483647

%define sys_getpid      39

section .text
    global  get_bet, get_amt, add_to_list, remove_from_list
    global  main
    extern  printf
    extern  srand, rand
    extern  malloc, free

    main:
        ; prologue
        push    rbp
        mov     rbp, rsp
        push    rbx
        push    r12
        push    r13
        push    r14
        push    r15
        pushf
        ; do we need stack variables ?
        ; let us use the multitude of registers available to us
        ; let R12 be head of the doubly-linked list
        ; let R13 be tail of the doubly-linked list
        ; let R14 be the winnings at the end
        ; let R15 be the number of chances
        xor     r12, r12
        xor     r13, r13
        xor     r14, r14
        xor     r15, r15

        ; First fill in the first 4 elements of the list
        xor     rax,rax
        mov     rdi, size_of_list
        call    malloc
        mov     r12, rax
        mov     [r12 + data_offset], dword 1
        xor     rax, rax
        mov     [r12 + prev_offset], rax
        mov     rdi, size_of_list
        call    malloc
        mov     [r12 + next_offset], rax
        mov     [rax + data_offset], dword 2
        mov     [rax + prev_offset], r12
        push    rax
        mov     rdi, size_of_list
        xor     rax, rax
        call    malloc
        pop     r8
        mov     [r8 + next_offset], rax
        mov     [rax + data_offset], dword 3
        mov     [rax + prev_offset], r8
        push    rax
        mov     rdi, size_of_list
        xor     rax, rax
        call    malloc
        pop     r8
        mov     [r8 + next_offset], rax
        mov     r13, rax
        mov     [r13 + data_offset], dword 4
        mov     [r13 + prev_offset], r8
        xor     rax, rax
        mov     [r13 + next_offset], rax

        mov     rax, sys_getpid
        syscall
        mov     rdi, rax
        call    srand
while_loop:
        cmp     r12,0
        jz      print_result
        cmp     r13,0 
        jz      print_result
        mov     rsi, r13
        mov     rdi, r12
        call    get_amt
        push    rax
        inc     r15

        mov     rsi, rax
        mov     rdi, dword int_format2
        xor     rax, rax
        call    printf

        call    get_bet
        pop     r10
        cmp     rax, 18
        jg      loss_block
win_block:
        add     r14, r10
        mov     rsi, r13
        mov     rdi, r12
        xor     rax, rax
        call    remove_from_list
        mov     rsi, r14
        mov     rdi, dword int_format0
        xor     rax, rax
        call    printf
        jmp     while_loop
loss_block:     
        sub     r14, r10
        mov     rsi, r10
        mov     rdi, r13
        call    add_to_list
        mov     r13, rax
        mov     rsi, r14
        mov     rdi, dword int_format1
        xor     rax, rax
        call    printf
        jmp     while_loop
print_result:   
        mov     rdx, r15
        mov     rsi, r14
        mov     rdi, dword prompt1
        xor     rax, rax
        call    printf
        ; epilogue with return value 0
        xor     rax,rax
        popf
        pop     r15
        pop     r14
        pop     r13
        pop     r12
        pop     rbx
        mov     rsp, rbp
        pop     rbp
        ret


remove_from_list:
        push    rbp
        mov     rbp, rsp
        push    rsi
        cmp     rdi, rsi
        je      free_tail_only
        cmp     rdi, 0
        jz      free_tail_only
        mov     r12, [rdi + next_offset]
        call    free ; on rdi
        cmp     r12, 0
        jz      free_tail_only
        xor     rcx, rcx
        mov     [r12 + prev_offset], rcx
free_tail_only:
        pop     rsi
        mov     rcx, rsi
        cmp     rsi, 0
        jz      ret_frm_rmvfrmlist
        mov     r13, [rsi + prev_offset]
        mov     rdi, rsi
        call    free
        cmp     r13, 0
        jz      ret_frm_rmvfrmlist
        xor     rcx, rcx
        mov     [r13 + next_offset],rcx
ret_frm_rmvfrmlist:
        xor     rax, rax
        mov     rsp, rbp
        pop     rbp
        ret
add_to_list:
        push    rbp
        mov     rbp, rsp
        push    rsi
        push    rdi
        mov     rdi, size_of_list
        call    malloc
        pop     rdi
        pop     rsi
        mov     [rdi + next_offset], rax
        cmp     rax, 0
        jz      ret_frm_add2list
        mov     [rax + data_offset], rsi
        xor     rcx, rcx
        mov     [rax + next_offset],rcx
        mov     [rax + prev_offset], rdi
ret_frm_add2list:
        mov     rsp, rbp
        pop     rbp
        ret

get_amt:
        push    rbp
        mov     rbp, rsp
        mov     rax, [rdi + data_offset]
        xor     rcx, rcx
        cmp     [rdi + next_offset],rcx
        jz      ret_frm_getamt
        add     rax, [rsi + data_offset]
ret_frm_getamt:
        mov     rsp, rbp
        pop     rbp
        ret

get_bet:
        push    rbp
        mov     rbp, rsp
        push    38
        push    RAND_MAX
        call    rand
        push    rax
        fild    qword [rbp - 24] ; rax
        fild    qword [rbp - 8]  ; 38
        fmulp   st1
        fild    qword [rbp - 16] ; RAND_MAX
        fld1
        faddp   st1
        fdivp   st1
        fistp   qword [rbp - 24]
        mov     rax, [rbp -24]
        mov     rsp, rbp
        pop     rbp
        ret

If the above assembly program was called roulette2.asm then executing the following statements would create the executable roulette2.out.

$ yasm -f elf64 roulette2.asm
$ ld -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
      /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o \
      roulette2.o  /usr/lib/x86_64-linux-gnu/crtn.o -lc -o roulette2.out

Download roulette2.asm.


LABOUCHERE SYSTEM C PROGRAM  |  x86-64 TUTORIAL: HILBERT MATRIX
SUPPORT THIS SITE
Donate DOGECOIN to DBevjMg3fd8C5oxZbV8sFpAffo6Tas1s8Q. DBevjMg3fd8C5oxZbV8sFpAffo6Tas1s8Q Donate BITCOIN to 19hrWWw1dPvBE1wVPfCnH8LqnUwsT3NsHW. 19hrWWw1dPvBE1wVPfCnH8LqnUwsT3NsHW
As an Amazon Associate I earn from qualifying purchases.