Hi,
Im trying to write a program that will ask the user to enter an N number between 2-f. Then accepts N inputs from user and sort them in ascending order. Below is what I have so far, but it is not working. Please help thanks.
DATA SEGMENT
MSG1 DB "How many integers would you like to enter? (Please enter from 2 to F)", "$"
N Db (?)
s db 20 dup (?) ; string to read/sort/print
swap db 1 dup (?) ; "swapped" flag
DATA ENDS
CODE SEGMENT
assume cs:code,ds:code
org 100h
START:
mov dx, offset MSG1
mov ah, 9
int 21h
mov ah,1 ; use DOS to read a character
int 21H
mov N,al
mov dx, offset N
mov ah, 9
int 21h
; read 10 characters
mov bx,offset s ; start of string
mov cl,N ; number of characters to read
READC:
mov ah,1 ; use DOS to read a character
int 21H
mov [bx],al ; store character in string
inc bx ; point to next character in string
dec cx ; decrement characters left to read
jnz readc ; repeat until all read
; bubble sort loop
SORT:
mov al,0 ; clear 'values swaped' flag
mov swap,al
mov bx,offset s ; point to first character
mov cx,9 ; set count to compare 9 pairs
NEXT2:
mov al,[bx] ; get character pair into al, ah
inc bx ; and point to next character
mov ah,[bx]
cmp ah,al ; compare the pair
jnc noswap ; skip the swap if first is <= second
mov [bx],al ; swap
dec bx
mov [bx],ah
inc bx
mov al,1 ; set "swapped" flag
mov swap,al
NOSWAP:
dec cx ; compare next pair if not done
jnz next2
mov al,swap ; do another pass if any swaps
cmp al,0
jnz SORT
; print results
mov bx,offset s ; start of string
mov cl,N ; number of characters to read
PRINTC:
mov ah,2 ; use DOS to print a character
mov dl,[bx] ;
int 21H
inc bx ; next character in string
dec cx ; decrement characters to print
jnz printc ; repeat until all printed
STOP:
mov ax, 4c00h
int 21h
CODE ENDS
END START
Apparently you want to create a program in COM format ( judging from the "org 100h" line )
To successfully create a COM file, you'll need a bit more bureaucracy. Add these lines to your prog:
DGROUP group CODE, DATA
DOSSEG
Also, you'll have to add a so-called class name to - at least - your CODE segment, because masm uses this name to determine if a segment is supposed to be a "code" segment; change line "CODE SEGMENT" to:
CODE SEGMENT "CODE"
There are a few more (minor) errors in your program, but at least it will now start correctly and you can use DEBUG to find them.
Japheth is trying to show you how to "combine" the data segment with the code segment
which is ok - but a bit overcomplicated
one of the rules for the old "tiny" .COM model is that all the code and data must be in the same segment or group that is less than (64 kb - 256) - the PSP uses 256 bytes
a much simpler method is to use a single segment
.MODEL Tiny
.386
OPTION CaseMap:None
;####################################################################################
.CODE
;************************************************************************************
ORG 100h
_main PROC NEAR
mov dx,offset s$Msg
mov ah,9
int 21h
mov ax,4C00h
int 21h
_main ENDP
;####################################################################################
s$Msg db 'Hello World !',0Dh,0Ah,24h
;####################################################################################
END _main
to build it, you need to use a 16-bit linker
ml /c /omf /AT MyFile.asm
link16 /TINY MyFile.obj,MyFile.exe;
Oops, bad idea, sorry.
Quote from: dedndave on October 26, 2013, 10:48:45 PM
Japheth is trying to show you how to "combine" the data segment with the code segment
which is ok - but a bit overcomplicated
Unless this is a school assignment and full segment definitions are required. Otherwise make it as simple as possible.
.model tiny
.386
.code
.startup
; entry point here
.exit
; data can go here
end
Hi dungeonfinder,
Michael is right and it's a good proposal. And welcome to the forum.
Gunther
Quote from: MichaelW on October 27, 2013, 02:46:38 AM
Unless this is a school assignment and full segment definitions are required. Otherwise make it as simple as possible.
Or, he/she might use an old version of Masm - or Tasm ( which was my consideration, because Masm doesn't understand the "(?)" syntax ).
Quote from: japheth on October 27, 2013, 01:52:32 PM
Or, he/she might use an old version of Masm - or Tasm ( which was my consideration, because Masm doesn't understand the "(?)" syntax ).
Yes. I think that TASM 5 can be downloaded for free since a few years.
Gunther
Quote from: dungeonfinder on October 26, 2013, 01:41:31 PM
DATA SEGMENT
MSG1 DB "How many integers would you like to enter? (Please enter from 2 to F)", "$"
N Db (?)
s db 20 dup (?) ; string to read/sort/print
swap db 1 dup (?) ; "swapped" flag
DATA ENDS
CODE SEGMENT
assume cs:code,ds:code
org 100h
START:
mov dx, offset MSG1
mov ah, 9
int 21h
mov ah,1 ; use DOS to read a character
int 21H
mov N,al
mov dx, offset N
mov ah, 9
int 21h
; read 10 characters
mov bx,offset s ; start of string
mov cl,N ; number of characters to read
READC:
mov ah,1 ; use DOS to read a character
int 21H
mov [bx],al ; store character in string
inc bx ; point to next character in string
dec cx ; decrement characters left to read
jnz readc ; repeat until all read
; bubble sort loop
SORT:
mov al,0 ; clear 'values swaped' flag
mov swap,al
mov bx,offset s ; point to first character
mov cx,9 ; set count to compare 9 pairs
NEXT2:
mov al,[bx] ; get character pair into al, ah
inc bx ; and point to next character
mov ah,[bx]
cmp ah,al ; compare the pair
jnc noswap ; skip the swap if first is <= second
mov [bx],al ; swap
dec bx
mov [bx],ah
inc bx
mov al,1 ; set "swapped" flag
mov swap,al
NOSWAP:
dec cx ; compare next pair if not done
jnz next2
mov al,swap ; do another pass if any swaps
cmp al,0
jnz SORT
; print results
mov bx,offset s ; start of string
mov cl,N ; number of characters to read
PRINTC:
mov ah,2 ; use DOS to print a character
mov dl,[bx] ;
int 21H
inc bx ; next character in string
dec cx ; decrement characters to print
jnz printc ; repeat until all printed
STOP:
mov ax, 4c00h
int 21h
CODE ENDS
END START
such a pleasure to read your program, I like your technique.
in this thread, i describe a bubble sort
it's 16-bit code - and works on byte arrays....
http://www.masmforum.com/board/index.php?topic=12740 (http://www.masmforum.com/board/index.php?topic=12740)
;--------------------------------------------------------------------------------------------
BSort PROC NEAR
;
;Byte Array Bubble Sort
;
;Call With: SI = address of array
; CX = size of array in bytes
;
; Returns: the array is sorted, lower values at lower addresses
;
; all general registers are used and not saved
;
;-------------------------------------------
jcxz BSort4 ;if array size = 0, sort is done
dec cx ;count to last byte
jz BSort4 ;if array size = 1, sort is done
mov bp,1 ;bp = 1 - used to set the swap flag
xor dx,dx ;dx = 0 - initial swap flag
cmp cx,bp ;if cx = 1, there are only 2 bytes
ja BSort0 ;more than 2 - skip the adjustment
mov bp,dx ;if only 2 bytes, we want one pass, so flag = 0
BSort0: add cx,si ;cx = top address
dec si ;adjust for the skip (DI gets ADD'ed before 1st pass)
mov di,-1 ;di = 1 for up, -1 for down (gets NEG'ed before 1st pass)
mov bx,si ;bx = bottom address (gets XCHG'ed with CX before 1st pass)
dec bx ;adjust for "one less" (DI gets SUB'ed before 1st pass)
BSort1: sub bx,di ;one less next time
xchg bx,cx ;swap ends
neg di ;switch direction
add si,di ;skip one - already did that pair
add si,di ;skip another one - one less next time
BSort2: mov ax,[si] ;get 2 bytes
cmp al,ah ;do they need to be swapped ?
jbe BSort3 ;no - next address
xchg al,ah ;yes - swap them
mov dx,bp ;set the swap flag
mov [si],ax ;store the swapped byte pair
BSort3: add si,di ;step in the current direction
cmp si,bx ;are we at the end ?
jnz BSort2 ;no - next pair
dec dx ;yes - clear the sort flag if it is 1
jz BSort1 ;if the sort flag was 1 before DEC, we are not done
BSort4: ret ;exit the routine
BSort ENDP
;--------------------------------------------------------------------------------------------
Such a great code Dave, and is faster.
you could eliminate the use of JCXZ, which is a slow instruction
or cx,cx
jz BSort4 ;if array size = 0, sort is done
dec cx ;count to last byte
jz BSort4 ;if array size = 1, sort is done
Dave,
Quote from: dedndave on November 04, 2013, 01:03:23 AM
you could eliminate the use of JCXZ, which is a slow instruction
or cx,cx
jz BSort4 ;if array size = 0, sort is done
dec cx ;count to last byte
jz BSort4 ;if array size = 1, sort is done
good proposal, but I think JCXZ isn't very critical in that case, because it's not inside the loop.
Gunther
probably right
but, i get chastised if i use JCXZ, LOOP, LODSB, STOSB, or XLAT :P
Quote from: dedndave on November 04, 2013, 01:13:52 AM
i get chastised if i use JCXZ
... and rightly so, at least in this case!
or cx,cx jz BSort4 dec cx ;count to last byte
jzjle BSort4 ;if array size = 1, sort is done
oops - what if the array is 65535 bytes ? :biggrin:
or 32769 to 65535, for that matter
JBE would work if DEC set the carry flag
probably the best code would be...
sub cx,1
jbe BSort4
Dave,
Quote from: dedndave on November 04, 2013, 05:27:02 AM
JBE would work if DEC set the carry flag
that won't work. Here's the explanation. (http://stackoverflow.com/questions/13435142/why-the-inc-and-dec-instructions-do-not-affect-the-carry-flag)
Gunther
right - that's why i suggested SUB CX,1
Dave,
Quote from: dedndave on November 04, 2013, 07:41:17 AM
right - that's why i suggested SUB CX,1
So we are on the safe side.
Gunther
Quote from: dedndave on November 04, 2013, 05:27:02 AM
oops - what if the array is 65535 bytes ? :biggrin:
or 32769 to 65535, for that matter
Quote from: dungeonfinder on October 26, 2013, 01:41:31 PM
MSG1 DB "How many integers would you like to enter? (Please enter from 2 to F)", "$"
0fh aka 15 is way below 32769...
ok - but the routine was intended to be more generic :P
you probably knew that - lol
Quote from: dedndave on November 04, 2013, 10:13:11 AM
you probably knew that - lol
I would never expect an array with more than 32768 members if total memory was only 640k ;-)
you're kidding, right ?
i used arrays larger than 64 kb sometimes