flat assembler
Message board for the users of flat assembler.

Index > Windows > chastdin calculator for Windows

Author
Thread Post new topic Reply to topic
chastitywhiterose



Joined: 13 Oct 2025
Posts: 69
chastitywhiterose 23 Jul 2026, 01:50
I am really bad at Windows Assembly but I managed to port over one of my Linux Assembly programs to Windows 32 API. It is a calculator in postfix notation. It can add, subtract, multiply, divide (div for quotient and rem for remainder). I even included a setradix command which takes the top number on the stack and sets the current radix. The default radix is ten because most humans are used to it but binary is my favorite obviously.

Also, I was very careful and tried to add error checking so there are no segmentation faults.

Code:
format PE console
include 'win32ax.inc'

include 'chastelibw32.asm'
include 'chastdinw32.asm'

main:

mov dword[radix],10    ;I can choose the radix for integer output!
mov dword[int_width],1 ;and the width of each integer for padded zeros

mov ebp,chastack       ;mov the address of the beginning of the stack to ebp registers

;this program does not read command line arguments
;it always displays a message to tell user what the program does
mov eax,string_help
call putstring

mov [last_char],0xA ;set newline as last_char so prompt will display

main_loop:

;show the arrow indicating we wait for the user to enter something
;but only show it when the last character is a newline
;otherwise it will print too many if multiple commands were entered on the same line
cmp [last_char],0xA
jnz skip_prompt
mov eax,string_prompt
call putstring
skip_prompt:

call getstring ;get string and return address in eax

;we must restart the loop in case of an empty string
;if we didn't, strint would read the empty string and return 0
;then zero would be pushed to the stack, which is not what we want

cmp dword[count],0 ;were there zero characters read?
jz main_loop ;if yes, this was an empty string, retry input

mov esi,eax    ;mov string to esi for string comparison

;Now we process the string the user entered
;First, we will try testing for commands
;If any of the predefined strings match the string in esi
;We jump to the label for that command

mov edi,string_setradix
call strcmp
jz command_setradix

mov edi,string_add
call strcmp
jz command_add

mov edi,string_sub
call strcmp
jz command_sub

mov edi,string_mul
call strcmp
jz command_mul

mov edi,string_div
call strcmp
jz command_div

mov edi,string_rem
call strcmp
jz command_rem

mov edi,string_query
call strcmp
jz command_query

mov edi,string_clear
call strcmp
jz command_clear

mov edi,string_exit
call strcmp
jz command_exit

;The default command is to turn the argument into a number and push to stack
command_num:

mov eax,esi          ;mov the string to eax for processing numbers
call strint          ;try to get a number from the string pointed to by eax
cmp [strint_error],0 ;did we have zero errors in the strint function?
jz num_push          ;if there were no errors, push this to stack

mov eax,string_err
call putstring       ;print error message
mov eax,esi
call putstring       ;print which command failed
call putline
jmp num_push_end     ;skip the push because this can't be used

num_push:            ;push the number to the fake stack
add ebp,4            ;increment the pointer by the size of the native int for this mode
mov [ebp],eax        ;mov the value we converted from the string with strint
num_push_end:
jmp main_loop        ;once value is pushed, continue the program

;These are the labels and code for each of the commands
;When a command is done, we jump back to the beginning of the loop
;the add,sub,mul,div,rem commands are pretty self explanatory
;but I will provide comments for these and other commands

;pop top of stack and set the current radix to it
;it has error checking and leaves the radix as is
;unless at least one number is on the stack
command_setradix:
cmp ebp,chastack      ;is ebp above the address of stack start?
jna change_radix_no   ;if not above, we cannot use it to set the radix
change_radix_yes:
mov eax,[ebp]         ;get the top of stack
mov [radix],eax       ;change the radix
mov dword[ebp],0      ;erase the top of stack
sub ebp,4             ;subtract pointer
jmp main_loop         ;and continue main_loop as normal
change_radix_no:
mov eax,string_err1   ;get error message for less than 1 numbers on stack
call putstring        ;print error message
mov eax,esi           ;get name of the command used
call putstring        ;print which command failed
call putline
jmp main_loop

;add number on top of stack to the one below it
command_add:
mov eax,[ebp]
sub ebp,4
add [ebp],eax
jmp memory_check ;check stack for errors after this command

;subtract number on top of stack from the one below it
command_sub:
mov eax,[ebp]
sub ebp,4
sub [ebp],eax
jmp memory_check ;check stack for errors after this command

;multiply number on top of stack by the one below it
command_mul:
mov ebx,[ebp]
sub ebp,4
mov eax,[ebp]
mov edx,0     ;zero edx before multiply
mul ebx       ;multiply eax with value in ebx
mov [ebp],eax
jmp memory_check ;check stack for errors after this command

;divide number on top of stack into the one below it
command_div:
mov ebx,[ebp]
sub ebp,4
mov eax,[ebp]
mov edx,0 ;zero edx before divide
div ebx   ;divide eax with value in ebx
mov [ebp],eax ;store quotient on stack
jmp memory_check ;check stack for errors after this command

;divide number on top of stack into the one below it
;but leave remainder instead of quotient
command_rem:
mov ebx,[ebp]
sub ebp,4
mov eax,[ebp]
mov edx,0 ;zero edx before divide
div ebx   ;divide eax with value in ebx
mov [ebp],edx ;store remainder on stack
jmp memory_check ;check stack for errors after this command

;check if the stack has enough space for the last command
;this will print an error if less than two numbers were on the stack
;when using one of the math commands above
memory_check:
cmp ebp,chastack      ;is ebp above the address of stack start?
jna print_stack_error ;if not above, explain error to user
mov dword[ebp+4],0    ;if no error, erase the old top of stack
jmp main_loop         ;and continue main_loop as normal
print_stack_error:
mov eax,string_err2  ;get error message for less than 2 numbers on stack
call putstring       ;print error message
mov eax,esi          ;get name of the command used
call putstring       ;print which command failed
call putline
add ebp,4            ;increment the pointer to what it was before the failed command
jmp main_loop

command_query: ;print all numbers on the stack
push ebp ;save value of ebp
command_query_loop:
cmp ebp,chastack ;is ebp equal to the address of stack start?
jz command_query_end  ;if it is, end the putstack loop
mov eax,[ebp]
sub ebp,4
call putint_and_line
jmp command_query_loop
command_query_end:
pop ebp ;restore ebp to what it was before this command
jmp main_loop

command_clear: ;erase all numbers on the stack
command_clear_loop:
cmp ebp,chastack ;is ebp equal to the address of stack start?
jz command_clear_end  ;if it is, end the putstack loop
mov dword[ebp],0
sub ebp,4
jmp command_clear_loop
command_clear_end:
jmp main_loop

command_exit: ;end the program

main_loop_end:

;Exit the process with code 0
push 0
call [ExitProcess]

.end main

argc dd 0

string_setradix db 'setradix',0
string_add db 'add',0
string_sub db 'sub',0
string_mul db 'mul',0
string_div db 'div',0
string_rem db 'rem',0

string_exit db 'exit',0
string_query db '?',0
string_clear db 'clear',0

string_prompt db '-> ',0

string_err db 'Error: invalid number or command: ',0 ;Generic error message
string_err1 db 'Error: need one number on stack for command: ',0 ;math fail error when less than one number on the stack
string_err2 db 'Error: need two numbers on stack for command: ',0 ;math fail error when less than two numbers on the stack

string_help db 'chastdin is a stack based interactive calculator',0xA
            db 'Numbers are pushed on the stack and commands can do math.',0xA
            db 'It is a fork of chastack that reads from stdin instead of arguments.',0xA
            db 'Each line can contain multiple numbers or commands.',0xA
            db 'Math commands are add,sub,mul,div,rem',0xA
            db 'The exit command ends the program',0xA
            db 'The ? command prints the entire stack',0xA,0xA,0

;This program uses a virtual stack for convenience and portability
;I allocate memory for a virtual stack that we can index as if it was the real stack
;I name it "chastack" for Chastity's stack.

chastack: rd 0x100
    


Description: getting standard input and comparing strings
Download
Filename: chastdinw32.asm
Filesize: 7.8 KB
Downloaded: 15 Time(s)

Description: integer and text output/conversion
Download
Filename: chastelibw32.asm
Filesize: 8.24 KB
Downloaded: 16 Time(s)

Post 23 Jul 2026, 01:50
View user's profile Send private message Send e-mail Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.