Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
averov90 committed Jan 3, 2021
0 parents commit 25ab034
Show file tree
Hide file tree
Showing 6 changed files with 686 additions and 0 deletions.
24 changes: 24 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <https://unlicense.org>
42 changes: 42 additions & 0 deletions README-eng.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# asm8086 IO and Ariphmetic example
[![License](https://img.shields.io/badge/LICENSE-The%20Unlicense-green?style=flat-square)](/LICENSE) [![Version](https://img.shields.io/badge/VERSION-STABLE-green?style=flat-square)](https://github.com/averov90/asm8086-io-ariphmetic/releases)
### :small_orange_diamond: [Russian version](/README.md)

This repository contains 3 small running programs that contain some I/O and arithmetic functions. To get an example (to be able to demonstrate), each program has a head function. Below, the list of examples will be discussed in more detail.

To run the examples, you need: a *DOS* environment, a *TASM (Turbo Assembler)* compiler for *Intel 8086*. As a *DOS* environment, you can take *DOSBox* (or *DOSBox Staging*, but in the *DOSBox*, compiled programs seem to work better).

Before starting each function, it is specified which registers are required for this function to work (i.e., those registers whose value must be stored before calling the function in case the values stored in them are needed later). These registers also include function arguments. The description of these arguments is given inside the function (at the beginning). Many aspects of program execution are explained in the comments in the code.

## prog_1.asm
**func_uint16IN** - function for entering an unsigned 16-bit number. The number itself is returned after entering via the *AX* register.

**func_uint32OUT** - function for outputting an unsigned 32-bit number. The number for output is supplied via 2 registers (*AX* - lower word, *DX* - upper word). In operation, this function uses a stack (requires 10 words, i.e. 20 bytes).

**func_mul32x16** - function for multiplying a 32-bit number by a 16-bit number. The numbers for are fed through 3 registers (*AX* - the lower word of 1 number, *DX* - the upper word of 1 number, *BX* - the multiplier). The result is via *AX* and *DX*.

**func_div32x16** - function for dividing a 32-bit number by a 16-bit number. Numbers for output are fed through 2 registers (*AX* - the lower word of 1 number, *DX* - the upper word of 1 number, *BX* - the multiplier) and the variable *func_div32x16_divider*. The result is in terms of *AX* and *DX* (integer part), *BX* - remainder.

The main function of this example uses the above functions to calculate the number of permutations when *m* and *n* are passed to the program.

## prog_2.asm
**func_int16IN** - function for entering a signed 16-bit number. The number itself is returned after entering via the *AX* register.

**func_uint16IN** - function for entering an unsigned 16-bit number. The number itself is returned after entering via the *AX* register.

**func_uint16OUT** - function for outputting an unsigned 16-bit number. The number for output is supplied through 2 registers (*AX* - the lower word). In operation, this function uses a stack (requires 10 words, i.e. 20 bytes).

The main function of this example uses the above functions to count the number of numbers greater than the specified threshold. Allows you to enter both the threshold and the number of numbers to enter.

## prog_3.asm
**func_placments32x16x16** - function for calculating the number of permutations for *m* and *n* passed to the program. Arguments to the function are passed through the stack.

**func_uint16IN** - function for entering an unsigned 16-bit number. The number itself is returned after entering via the *AX* register.

**func_uint32OUT** - function for outputting an unsigned 32-bit number. The number for output is supplied via 2 registers (*AX* - lower word, *DX* - upper word). In operation, this function uses a stack (requires 10 words, i.e. 20 bytes).

**func_mul32x16** - function for multiplying a 32-bit number by a 16-bit number. The numbers for are fed through 3 registers (*AX* - the lower word of 1 number, *DX* - the upper word of 1 number, *BX* - the multiplier). The result is via *AX* and *DX*.

**func_div32x16** - function for dividing a 32-bit number by a 16-bit number. Numbers for output are fed through 2 registers (*AX* - the lower word of 1 number, *DX* - the upper word of 1 number, *BX* - the multiplier) and the variable *func_div32x16_divider*. The result is in terms of *AX* and *DX* (integer part), *BX* - remainder.

The main function of this example uses the above functions to calculate the number of permutations when *m* and *n* are passed to the program.
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# asm8086 IO and Ariphmetic example
[![License](https://img.shields.io/badge/LICENSE-The%20Unlicense-green?style=flat-square)](/LICENSE) [![Version](https://img.shields.io/badge/VERSION-STABLE-green?style=flat-square)](https://github.com/averov90/asm8086-io-ariphmetic/releases)
### :small_orange_diamond: [English version](/README-eng.md)

В данном репозитории представлены 3 небольшие работающие программы, которые содержат некоторые функции ввода/вывода и арифметики. Для получения примера (чтобы была возможность демонстрации), в каждой программе есть головная функция. Ниже состав примеров будет рассмотрен подробнее.

Для запуска примеров необходимо: окружение *DOS*, компилятор *TASM (Turbo Assembler)* для *Intel8086*. В качестве окружения *DOS* можно взять *DOSBox* (либо *DOSBox Staging*, но в старом *DOSBox* скомпилированные программы работают, кажется, лучше).

Перед началом каждой функцией указано, какие регистры требуются этой функции для работы (т.е. те регистры, значение которых нужно сохранить перед вызовом функции в случае, если хранимые в них значения будут нужны позже). В число этих регистров входят и аргументы функции. Описание этих аргументов даётся внутри функции (в начале). Многие моменты выполнения программ пояснены в комментариях в коде.

## prog_1.asm
**func_uint16IN** - функция ввода беззнакового 16-битного числа. Само число после ввода возвращается через регистр *AX*.

**func_uint32OUT** - функция вывода беззнакового 32-битного числа. Число для вывода подаётся через 2 регистра (*AX* - нижнее слово, *DX* - верхнее слово). В работе данная функция использует стек (требует 10 слов т.е. 20 байт).

**func_mul32x16** - Функция умножения 32-битного числа на 16-битное. Числа для подаются через 3 регистра (*AX* - нижнее слово 1 числа, *DX* - верхнее слово 1 числа, *BX* - множитель). Результат - через *AX* и *DX*.

**func_div32x16** - функция деления 32-битного числа на 16-битное. Числа для вывода подаются через 2 регистра (*AX* - нижнее слово 1 числа, *DX* - верхнее слово 1 числа, *BX* - множитель) и переменную *func_div32x16_divider*. Результат - через *AX* и *DX* (целая часть), *BX* - остаток.

Головная функция данного примера с помощью вышеприведённых функций выполняет вычисление количества расстановок при переданных в программу *m* и *n*.

## prog_2.asm
**func_int16IN** - функция ввода знакового 16-битного числа. Само число после ввода возвращается через регистр *AX*.

**func_uint16IN** - функция ввода беззнакового 16-битного числа. Само число после ввода возвращается через регистр *AX*.

**func_uint16OUT** - функция вывода беззнакового 16-битного числа. Число для вывода подаётся через 2 регистра (*AX* - нижнее слово). В работе данная функция использует стек (требует 10 слов т.е. 20 байт).

Головная функция данного примера с помощью вышеприведённых функций выполняет подсчёт количества чисел, больших заданного порога. Позволяет ввести как порог, так и количество чисел для ввода.

## prog_3.asm
**func_placments32x16x16** - функция вычисления количества расстановок при переданных в программу *m* и *n*. Аргументы в функцию передаются через стек.

**func_uint16IN** - функция ввода беззнакового 16-битного числа. Само число после ввода возвращается через регистр *AX*.

**func_uint32OUT** - функция вывода беззнакового 32-битного числа. Число для вывода подаётся через 2 регистра (*AX* - нижнее слово, *DX* - верхнее слово). В работе данная функция использует стек (требует 10 слов т.е. 20 байт).

**func_mul32x16** - Функция умножения 32-битного числа на 16-битное. Числа для подаются через 3 регистра (*AX* - нижнее слово 1 числа, *DX* - верхнее слово 1 числа, *BX* - множитель). Результат - через *AX* и *DX*.

**func_div32x16** - функция деления 32-битного числа на 16-битное. Числа для вывода подаются через 2 регистра (*AX* - нижнее слово 1 числа, *DX* - верхнее слово 1 числа, *BX* - множитель) и переменную *func_div32x16_divider*. Результат - через *AX* и *DX* (целая часть), *BX* - остаток.

Головная функция данного примера с помощью вышеприведённых функций выполняет вычисление количества расстановок при переданных в программу *m* и *n*.
191 changes: 191 additions & 0 deletions prog_1.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
.model small

.stack 24 ;bytes, 10 - word - stack depth for func_uint32OUT, 2 - for funclion call

.data
;Constants
msg_enterM_err db 0Ah,'"m" must be above "n"! '
msg_enterM db 0Ah,'Enter "m": $'
msg_enterN_err db 0Ah,'"n" must be above or equal 0! '
msg_enterN db 'Enter "n": $'
msg_result db 0Ah,'Result: $'
msg_calc_error db 0Ah,'The result is too big!',0Ah,'Further calculation is not possible.$'
func_uint16IN_errmsg db 0Ah,'Invalid input! Enter 16-bit unsigned number: $'
func_div32x16_divider dw 10
;Multithread non-safe
func_uint16IN_buffer db 6, 0, 6 dup(?)

.code
start proc
mov ax, @data
mov ds, ax ;init data segment
lea dx, msg_enterN
N_reenter:
mov ah,9
int 21h ;message print
call func_uint16IN ;input number
test ax,ax
jz N_unc
mov di,ax ;di = n
lea dx, msg_enterM
M_reenter:
mov ah,9
int 21h ;message print
call func_uint16IN ;input number
cmp ax,di
jb M_unc
je N_decrease
next1:
xor dx,dx ;dx - result high word
sub di,1
jbe displ_result ;jump to skip loop
mov cx,di
mov bx,ax ;bx = m, ax - result low word
cloop:
dec bx
call func_mul32x16
jc calc_error
loop cloop
displ_result:
mov bx,ax
mov cx,dx ;save registers values
lea dx, msg_result
mov ah,9
int 21h ;message print
mov ax,bx
mov dx,cx ;restore saved registers values
call func_uint32OUT
mov ah, 4Ch
int 21h ;stop
calc_error:
lea dx, msg_calc_error
mov ah,9
int 21h
mov ah, 4Ch
int 21h ;stop
N_unc:
lea dx, msg_enterN_err
jmp N_reenter
N_decrease:
dec di
jmp next1
M_unc:
lea dx, msg_enterM_err
jmp M_reenter
start endp

;require: ax, bx, cx, dx, si
func_uint16IN proc
mov bx,10 ;prepare bx register
xor ch,ch
label_func_uint16IN_reinput:
lea dx, func_uint16IN_buffer ;set pointer to buffer
mov ah,0Ah ;init string input mode
int 21h ;input string
mov cl, [func_uint16IN_buffer+1]
lea si, func_uint16IN_buffer+2 ;set pointer to first symbol of string to si
xor ax,ax ;zero ax
label_func_uint16IN_loop:
cmp byte ptr [si],'0' ;check symbol code
jb label_func_uint16IN_err
cmp byte ptr [si],'9' ;check symbol code
ja label_func_uint16IN_err
mul bx ;multiply to basis
jc label_func_uint16IN_err
sub byte ptr [si],'0' ;get number from symbol
add al,[si] ;add number to result
adc ah,0
jc label_func_uint16IN_err
inc si
loop label_func_uint16IN_loop ;string to uint16 cycle
ret
label_func_uint16IN_err:
lea dx,func_uint16IN_errmsg
mov ah,9
int 21h
jmp label_func_uint16IN_reinput
func_uint16IN endp

;require: ax, bx, cx, dx, si, di
func_uint32OUT proc
;ax - low word
;dx - high word
xor cx,cx ;zero counter
label_func_uint32OUT_decodeNext:
inc cx ;count digits
call func_div32x16 ;get digit
push bx ;save digit
test ax,ax ;check that digits not finish
jnz label_func_uint32OUT_decodeNext ;if not - repeat
test dx,dx
jnz label_func_uint32OUT_decodeNext ;if not - repeat
mov ah,2 ;prepare DOS output
label_func_uint32OUT_printNext:
pop dx ;get digit
add dx,'0' ;set digit to output
int 21h
loop label_func_uint32OUT_printNext
ret
func_uint32OUT endp

;require: ax, bx, dx, si, di
func_mul32x16 proc
;ax - low word
;dx - high word
;bx - multiplier
mov si,ax ;prepare to high word multiply
mov ax,dx
mul bx
jo label_func_mul32x16_overflow
mov di,ax
mov ax,si ;prepare to low word multiply
mul bx
add dx,di
jc label_func_mul32x16_overflow
ret
label_func_mul32x16_overflow:
stc
ret
func_mul32x16 endp

;require: ax, bx, dx, si, di
func_div32x16 proc
;ax - low word input
;dx - high word input
;func_div32x16_divider - divider
;ax - low word quotient
;dx - high word quotient
;bx - remainder
test dx,dx
jz func_div32x16_simpleDiv
mov di,dx ;LW block - save high word
xor dx,dx
div [func_div32x16_divider] ;divide low word
mov bx,ax ;save quotient low word
mov si,dx ;save remainder low word
mov ax,di ;HW block
xor dx,dx
div [func_div32x16_divider] ;divide high word
mov di,ax ;save quotient high word
xor ax,ax ;HWR block
div [func_div32x16_divider] ;divide high word remainder
add bx,ax
adc di,0
mov ax,dx ;R block
xor dx,dx
add ax,si ;remainder summ
adc dx,0
div [func_div32x16_divider] ;divide remainder summ
add ax,bx
adc di,0
mov bx,dx ;result forming
mov dx,di ;high word to bx
ret
func_div32x16_simpleDiv:
div [func_div32x16_divider]
mov bx,dx
xor dx,dx
ret
func_div32x16 endp

end start
Loading

0 comments on commit 25ab034

Please sign in to comment.