Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP
Filename : MEMORY.ASM

 
Output of file : MEMORY.ASM contained in archive : EMAC15ES.ZIP
;History:409,1
;09-07-88 22:03:44 remove public margin
;04-07-88 00:08:22 remember to set buffer-modified on xlat_to_mark
;03-30-88 21:22:37 add xlat_to_mark
;11-16-87 23:13:40 move calculations involving memsize into buffers.asm
;11-15-87 00:04:12 call buffer_free.
;11-14-87 23:09:22 move toptop..botbot out of memory.
;07-15-87 23:31:17 get rid of dump_bufseg
;07-13-87 22:53:52 move init_memory to mintprim.asm

debugging equ 0

.xlist

HT equ 09h
LF equ 0ah
CR equ 0dh
LINENEW equ CR+LF*256 ;the way a newline is stored in memory.

bufseg segment public

extrn toptop: word
extrn topbot: word
extrn bottop: word
extrn botbot: word

public linecount, linesbefore
linecount dw ?
linesbefore dw ?

public buffer_modified
buffer_modified db ?

extrn bufseg_size: byte

bufseg ends

data segment byte public

;the following externs are in 'buffers'
extrn textseg: word

insert_ds dw ?

data ends

b_struc struc
b db ?
b_struc ends

w_struc struc
w dw ?
w_struc ends

byte_ptr label byte

code segment byte public
;all the routines in this segment are entered with ds=data, es=data
assume cs:code, ds:data, es:data

;the following externs are in 'marks'
extrn init_marks: near
extrn get_mark: near
extrn adjust_marks_del: near
extrn adjust_marks_ins: near

;the following externs are in 'redisp'
extrn prevline: near
extrn nextline: near
extrn compute_one: near


public count_lines
count_lines:
push ds
mov ds,textseg
call count_lines$
pop ds
ret

public del_to_mark
del_to_mark:
push ds
mov ds,textseg
call del_to_mark$
pop ds
ret


public read_mark
read_mark:
mov ds,textseg
call read_mark$
ret


public goto_mark
goto_mark:
push ds
mov ds,textseg
call goto_mark$
pop ds
ret


public xlat_to_mark
xlat_to_mark:
push ds
mov ds,textseg
call xlat_to_mark$
pop ds
ret


public insert_string
insert_string:
push ds
mov ax,es ;use data for insert_ds.
mov ds,textseg
call insert_string$
pop ds
ret


public set_column
set_column:
push ds
mov ds,textseg
call set_column$
pop ds
ret


public set_line
set_line:
push ds
mov ds,textseg
call set_line$
pop ds
ret


public compute_cursor
compute_cursor:
;exit with dx=column.
push ds
mov ds,textseg
call compute_cursor$
pop ds
ret


public store_buffer_modified
store_buffer_modified:
push ds
mov ds,textseg
assume ds:bufseg
mov buffer_modified,al
pop ds
assume ds:data
ret


public read_linecount
read_linecount:
mov bx,offset linecount
jmp short read_variable
public read_linesbefore
read_linesbefore:
mov bx,offset linesbefore
jmp short read_variable
public read_buffer_modified
read_buffer_modified:
mov bx,offset buffer_modified
read_variable:
push ds
mov ds,textseg
assume ds:bufseg
mov ax,bufseg:[bx]
pop ds
assume ds:data
ret


public file_size
file_size:
;exit with ax=size of the current buffer in bytes.
mov ds,textseg
assume ds:bufseg

mov ax,topbot
sub ax,toptop
add ax,botbot
sub ax,bottop
push es
pop ds
assume ds:data
ret


code ends

code segment byte public
;all the code in this segment is entered with ds=bufseg, es=data
assume cs:code, ds:bufseg, es:data

;the following externs are in 'redisp'
extrn paint_window: near
extrn trash_line: near
extrn window_insert: near
extrn window_delete: near
extrn up_lines: near
extrn down_lines: near

public init_vars$
init_vars$:
mov bx,offset bufseg_size+2
mov [bx-02].w,LINENEW
mov toptop,bx
mov topbot,bx
mov bottop,bx
mov botbot,bx
mov linecount,0
mov linesbefore,0
mov buffer_modified,0
ret


extrn buffer_free: near

public insert_string$
insert_string$:
;enter with si,cx describing the string to insert, ax=segment of string.
;exit with cy if there isn't enough room to insert the entire string.
jcxz insert_string_1
mov es,ax ;put it where we need it.
mov ax,ds
call buffer_free
mov ss:insert_ds,es ;remember what it is now.
push ss
pop es
jc insert_string_4 ;no - give error.
mov buffer_modified,1
insert_string_2:
push ds
mov ds,insert_ds
mov ax,ds:[si] ;get an entire word, even though we might use only the low byte.
pop ds
cmp ax,LINENEW ;newline?
jne insert_string_3 ;no.
cmp cx,2 ;must be at least two chars left.
jb insert_string_3 ;no - can't be newline.
push cx
push si
call inscrlf
pop si
pop cx
add si,2
dec cx
loop insert_string_2
jmp short insert_string_1
insert_string_3:
push cx
push si
call insone
pop si
pop cx
inc si
loop insert_string_2
insert_string_1:
clc
ret
insert_string_4:
stc
ret


insone:
cmp al,CR
jne insone_1
mov bx,bottop
cmp [bx].b,LF
jne inschar
inc bottop
jmp short insone_2
insone_1:
cmp al,LF
jne inschar
mov bx,topbot
cmp [bx-01].b,CR
jne inschar
dec topbot
insone_2:
mov ax,1
call adjust_marks_del
call inscrlf
ret

inschar:
;insert the character in al at the point.
;unless there is no room.
mov bx,topbot
cmp bx,bottop
jae inschar_1
push ax
mov ax,1
call adjust_marks_ins
pop ax
mov di,topbot
mov [di],al
inc di
mov topbot,di
call trash_line
inschar_1:
ret


inscrlf:
mov bx,topbot
inc bx
cmp bx,bottop
jae inscrlf_3

mov ax,2
call adjust_marks_ins

mov di,topbot
mov [di].w,LINENEW
add di,2
mov topbot,di

inc linesbefore
inc linecount

call window_insert ;say that we inserted a line here.

inscrlf_3:
ret


del_to_mark$:
call get_mark
jcxz del_to_mark_4_j_1
mov buffer_modified,1
jc del_to_mark_2 ;go if point>mark
push bottop
call move_point_backward ;swap point and mark (sort of).
pop si ;pushed as bottop.
del_to_mark_2:
mov di,toptop ;are we at the beginning of the file?
cmp di,topbot
jne del_to_mark_1 ;no
cmp si,botbot ;deleting to the end of the file?
jne del_to_mark_1 ;no
mov ax,si
sub ax,bottop ;compute the number of chars deleted.
mov bottop,si ;no characters left.
call adjust_marks_del
mov linecount,0 ;no lines left.
call paint_window ;trash the window.
del_to_mark_4_j_1:
jmp short del_to_mark_4 ;now exit.
del_to_mark_1:
mov bp,si ;save the char that we delete to.
mov ax,si ;compute the number of chars.
sub ax,bottop
call adjust_marks_del ;fix up the marks first.
mov si,bottop ;get the -> first char to delete.
del_to_mark_3:
cmp [si].w,LINENEW ;a newline?
jne del1_1 ;no - just skip this char.
inc si ;extra inc to skip past the CR.
dec linecount ;one less line.
call window_delete ;fix up the window.
del1_1:
inc si
cmp bp,si
jne del_to_mark_3
mov bottop,si
call trash_line
;now check for a newly created newline.
mov bx,topbot
cmp [bx-1].b,CR
jne del_to_mark_4
mov bx,bottop
cmp [bx].b,LF
jne del_to_mark_4
;get rid of the LF and CR seperately so that any mark that points to either
; one will point to the newline.
inc bottop ;get rid of the LF
mov ax,1
call adjust_marks_del
dec topbot ;get rid of the CR
mov ax,1
call adjust_marks_del
call inscrlf ;now insert a newline.
del_to_mark_4:
ret


xlat_to_mark$:
;enter with al =mark, bx,dx ->translate string.
push bx
push dx
call read_mark$
pop dx
pop bx
jcxz xlat_to_mark_2 ;quit if no chars in the region.
mov buffer_modified,1
xlat_to_mark_1:
cmp word ptr [si],LINENEW ;is this a newline?
jne xlat_to_mark_3
add si,2 ;yes - skip it.
dec cx
jmp short xlat_to_mark_4
xlat_to_mark_3:
lodsb ;translate the character.
cmp al,dl ;is this character in the translate char?
jae xlat_to_mark_4 ;yes - it is.
xlat es:[bx]
mov [si-1],al
xlat_to_mark_4:
loop xlat_to_mark_1
xlat_to_mark_2:
call paint_window ;trash the window.
ret


public goto_mark$
goto_mark$:
call get_mark
jcxz goto_mark_1
jnc goto_mark_2
call move_point_forward
jmp short goto_mark_1
goto_mark_2:
call move_point_backward
goto_mark_1:
ret


public read_mark$
read_mark$:
call get_mark
jnc read_mark_1
mov si,bottop
read_mark_1:
ret


move_point_backward:
mov si,topbot
mov di,bottop
push es
push ds
pop es
std
dec si
dec di
push cx
rep movsb
pop cx
inc si
inc di
cld
pop es
mov topbot,si
mov bottop,di
call count_lines$
sub linesbefore,bx
call up_lines
ret


move_point_forward:
mov si,bottop
mov di,topbot
push di
push cx
push es
push ds
pop es
rep movsb
pop es
mov bottop,si
mov topbot,di
pop cx
pop di
call count_lines$
add linesbefore,bx
call down_lines
ret


count_lines$:
;count the number of newlines contained in the text described by ds:di,cx.
push es
push ds
pop es
mov bx,0
count_lines_1:
mov al,CR
repnz scasb
jcxz count_lines_2
cmp [di].b,LF
jne count_lines_1
inc bx
jmp count_lines_1
count_lines_2:
pop es
ret


public set_line$
set_line$:
;given a line number in ax, move to that line.
dec ax ;linesbefore is zero based.
or ax,ax ;if negative, use zero.
jns set_line_0
xor ax,ax
set_line_0:
sub ax,linesbefore
je set_line_1 ;go if we're already on that line.
jb set_line_2 ;go if we're after that line.
mov cx,ax
mov si,bottop
set_line_4:
call nextline
loopne set_line_4
mov cx,si ;compute the number of characters.
sub cx,bottop
call move_point_forward
jmp short set_line_1
set_line_2:
neg ax ;ax is the number of lines to move.
mov cx,ax
mov si,topbot
cmp [si-2].w,LINENEW ;are we at the beginning of a line?
je set_line_3 ;yes.
call prevline ;no, go to the beginning of the line.
set_line_3:
call prevline
loopne set_line_3
mov cx,topbot ;compute the number of characters.
sub cx,si
call move_point_backward
set_line_1:
ret


set_column$:
;given a column number in ax, move to that column.
mov bx,ax ;save the column number in bx.
dec bx ;columns are zero based.
mov si,topbot
jmp short set_column$_2
set_column$_1:
dec si
set_column$_2:
cmp [si-2].w,LINENEW
jne set_column$_1
;now move over to the point, counting the size of characters on the way.
mov dx,0
mov cx,topbot
sub cx,si
jcxz set_column$_3
set_column$_4:
cmp dx,bx ;are we at or past the desired column?
jae set_column$_6 ;yes - move the point backward.
lodsb
call compute_one
loop set_column$_4
set_column$_3:
;the desired column is somewhere after the point.
mov si,bottop
set_column$_7:
cmp dx,bx ;are we at or past the desired column?
jae set_column$_5 ;yes - go to the column.
cmp si,botbot ;did we hit eof?
je set_column$_5 ;yes - this is as close as we can get.
cmp [si].w,LINENEW ;are we at the end of the line?
je set_column$_5 ;yes - this is as close as we can get.
lodsb ;compute the next character.
call compute_one
jmp set_column$_7
set_column$_5:
mov cx,si
sub cx,bottop
call move_point_forward
ret
set_column$_6:
call move_point_backward
ret


public compute_cursor$
compute_cursor$:
;return the column in dx.
;find the beginning of this line.
mov si,topbot
jmp short compute_cursor$_2
compute_cursor$_1:
dec si
compute_cursor$_2:
cmp [si-2].w,LINENEW
jne compute_cursor$_1
;now move over to the point, counting the size of characters on the way.
mov dx,0
mov cx,topbot
sub cx,si
jcxz compute_cursor$_3
compute_cursor$_4:
lodsb
call compute_one
loop compute_cursor$_4
compute_cursor$_3:
ret


code ends

end


  3 Responses to “Category : Assembly Language Source Code
Archive   : EMAC15ES.ZIP
Filename : MEMORY.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/