0xDE5

Trying to solve and expand 0xde5 exercises in assembly (or C)
git clone git://git.mdnr.space/0xDE5
Log | Files | Refs | README | LICENSE

rpn.s (3938B)


      1 # --------------------- CONSTANTS ------------------------- #
      2 
      3 .set SYSCALL_READ, 0
      4 .set SYSCALL_WRITE, 1
      5 .set SYSCALL_OPEN, 2
      6 .set SYSCALL_CLOSE, 3
      7 .set SYSCALL_EXIT, 60
      8 .set SYSCALL_GETRLIMIT, 97
      9 
     10 .set RLIMIT_STACK, 3
     11 
     12 .set STDIN, 0
     13 .set STDOUT, 1
     14 .set STDERR, 2
     15 
     16 # --------------------- DATA ------------------------- #
     17     .data
     18 
     19 result_msg:
     20     .asciz "Result = "
     21 result_msg_len = . - result_msg
     22 
     23 error_msg:
     24     .asciz "[ERROR] File not fuond\n"
     25     error_msg_len = . - error_msg
     26 
     27 usage_msg:
     28     .asciz "Usage: rpn <file>\n"
     29     usage_msg_len = . - usage_msg
     30 
     31 newline:
     32     .asciz "\n"
     33 
     34 .bss
     35     read_char_buf: .space 1
     36     digit: .space 1
     37 
     38     rlimit:  .space 16
     39     # struct rlimit {
     40     #     unsigned long rlim_cur;  // Soft limit (current limit)
     41     #     unsigned long rlim_max;  // Hard limit (maximum limit)
     42     # };
     43     # although we will only use the soft limit value
     44 
     45 
     46 
     47 
     48 # --------------------- CODE ------------------------- #
     49     .global _start
     50 
     51 .text
     52 
     53 _start:
     54 
     55     mov (%rsp), %rbx # (%rsp) is argc
     56     cmp $1, %rbx
     57     jle .L_print_usage
     58     cmp $3, %rbx
     59     jge .L_print_usage
     60 
     61     call .F_get_stack_size # get the soft limit for stack and store it in rlimit
     62 
     63     # Devide the maximum stack size by 2, because we're pussies
     64     mov rlimit, %rax
     65     shr $1, %rax
     66     mov %rax, rlimit
     67 
     68     pop %rdi # argc
     69     pop %rdi # argv[0]
     70     pop %rdi # argv[1]
     71     # Try to open the file
     72     mov $SYSCALL_OPEN, %rax
     73     xor %rdx, %rdx
     74     xor %rsi, %rsi
     75     syscall
     76 
     77     mov %rax, %rdi
     78     cmp $0, %rdi
     79     jg .L_read_char_from_file
     80     mov $SYSCALL_WRITE, %rax
     81     mov $STDERR, %rdi
     82     mov $error_msg, %rsi
     83     mov $error_msg_len, %rdx
     84     syscall
     85     jmp .L_exit
     86 
     87 .L_read_char_from_file:
     88     mov $SYSCALL_READ, %rax
     89     mov $read_char_buf, %rsi
     90     mov $1, %rdx
     91     syscall
     92 
     93     cmpb $' ', (%rsi)
     94     je .L_read_char_from_file
     95     cmpb $48, (%rsi) # compare with 0, "+ - * /" are less that 0 in ascii table
     96     jb .L_check_end
     97     subq $48, (%rsi) # convert to integer
     98     xor %rax, %rax
     99     movb (%rsi), %al
    100     push %rax
    101     jmp .L_read_char_from_file
    102 .L_check_end:
    103     cmpb $'\n', (%rsi)
    104     jne .L_do_operation
    105     pop %r8
    106     call .F_prepare_result
    107     jmp .L_exit
    108 
    109 .L_do_operation:
    110     # if we reach hre it means we have read an operator
    111     pop %rcx # restore last number from stack
    112     pop %rax # restore 1 before last number from stack
    113 div:
    114     cmpb $47, (%rsi) # compare with /
    115     jne mul
    116     xor %rdx, %rdx
    117     div %rcx
    118     push %rax
    119     jmp .L_read_char_from_file
    120 
    121 
    122 mul:
    123     cmpb $42, (%rsi) # compare with *
    124     jne addition
    125     mul %rcx
    126     push %rax
    127     jmp .L_read_char_from_file
    128 
    129 addition:
    130     cmpb $43, (%rsi) # compare with +
    131     jne subtract
    132     add %rcx, %rax
    133     push %rax
    134     jmp .L_read_char_from_file
    135 
    136 subtract:
    137     sub %rcx, %rax
    138     push %rax
    139     jmp .L_read_char_from_file
    140 
    141     .L_print_usage:
    142     mov $SYSCALL_WRITE, %rax
    143     mov $STDERR, %rdi
    144     mov $usage_msg, %rsi
    145     mov $usage_msg_len, %rdx
    146     syscall
    147 
    148     .L_exit:
    149     mov $60, %rax
    150     xor %rdi, %rdi
    151     syscall
    152 
    153 
    154 # --------------------- FUNCTIONS ------------------------- #
    155 
    156 .F_get_stack_size:
    157     mov $SYSCALL_GETRLIMIT, %rax
    158     mov $RLIMIT_STACK, %rdi
    159     mov $rlimit, %rsi
    160     syscall
    161     ret
    162 
    163 # arguments: result value in r8
    164 .F_prepare_result:
    165     mov $SYSCALL_WRITE, %rax
    166     mov $STDOUT, %rdi
    167     mov $result_msg, %rsi
    168     mov $result_msg_len, %rdx
    169     syscall
    170     mov %r8, %rax
    171     mov $10, %r8
    172     xor %rcx, %rcx
    173 .L_next:
    174     xor %rdx, %rdx
    175     div %r8
    176     push %rdx
    177     inc %rcx
    178     cmp $0, %rax
    179     ja .L_next
    180 .L_get_digits:
    181     pop %rdx
    182     add $'0', %rdx
    183     mov %rdx, digit
    184     lea digit, %rsi
    185     mov $1, %rdx
    186     push %rcx
    187     call .F_print
    188     pop %rcx
    189     loop .L_get_digits
    190 
    191     mov $newline, %rsi
    192     mov $1, %rdx
    193     call .F_print
    194     ret
    195 
    196 
    197     # arguments: 1. address of string: rsi
    198     #            2. length of the string: rdx
    199 .F_print:
    200     mov $SYSCALL_WRITE, %rax
    201     mov $STDOUT, %rdi
    202     syscall
    203     ret
    204