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