How to disable screen in Commodore 64? - c64

I know this question is very spesific question but I know there are some c64 code gurus around here. So, here is my question.
When I try to disable screen using $d011 trick, upper/lower border also opens. I want to do that without opening upper/lower borders. Is it possible?

Oh, a c64 question. Nice. :) I have one sample in my code archive. You need to do the $d011 trick at the beginning of the screen, not at the end.
This is an ACME source code.
!to "nobadlines.prg",cbm
!macro WAIT .v {
ldy #.v
dey
bne *-1
}
* = $0801
!byte $0c, $08, $00, $00, $9e, $32, $30, $36, $31, $00, $00, $00
* = $080d
lda #$01
sta $3fff
sei
start:
lda #$30
cmp $d012
bne *-3
lda #$00
sta $d011
+WAIT 24
lda #$0b
sta $d011
lda #$31
cmp $d012
bne *-3
lda #$1b
sta $d011
+WAIT 8
bit $ea
ldx #$00
loop1:
txa
sta $d020
sta $d021
+WAIT 9
inx
cpx #254
bne loop1
asl $3fff
bne start
inc $3fff
jmp start

Related

How do I put this code in a loop in edsim51?

My code isn't working despite not showing any errors, so I believe it's because I'm doing the loop the wrong way.
The objective would be that when key 1 was pressed the displayed value would increase by +1, and if key 0 was pressed the opposite would happen.
I tried to put "loop:" at the beginning of the code that I want to be in a loop but it didn't work, only 50 appears in memory, which would be the base value, but I can't increase or decrease it.
Code:
display equ 20h
contador equ 60h
MOV A,contador
ADD A,#50
MOV contador,A
LOOP:
IF: ;SE 1 FOR PRESSIONADO ADICIONA 1
JB p2.1, FIM_IF
INC contador
WAIT:
JNB p2.1 ,WAIT
FIM_IF:
IF2: ;SE 0 FOR PRESSIONADO SUBTRAI 1
JB p2.0, FIM_IF2
DEC contador
WAIT2:
JNB p2.0,WAIT2
FIM_IF2:
IF3: ;SE FOR MAIOR QUE 99 VOLTA A 0
MOV A,#99
CLR C
SUBB A,contador
JNC FIM_IF3
;VOLTA O CONTADOR PARA 0
MOV A,contador
SUBB A,#100
MOV contador,A
FIM_IF3:
IF4: ;SE FOR MENOR QUE 0 VOLTA A 99
MOV A,contador
CLR C
SUBB A,#0
JNC FIM_IF4
;volta o contador para o 99
MOV A,contador
ADD A,#100
MOV contador,A
FIM_IF4:
;apresenta o valor na memoria
mov a,contador
mov b,#10
div ab
rl a
rl a
rl a
rl a
orl a,b
mov display,a

check positive number assembly8086

iam trying to write an assembly code 8086 i have two array X AND Y size 10 and i want to enter a number and check if its positive y will be 1 if negative it will be 0
but my code just displayed what i enter a number but i want it like this example .
example:
X : 2 -5 -7 8 -4 9 11 -12 90 -50
Y : 1 0 0 1 1 0 1 1 0 1 0
I wrote:
.MODEL SMALL
.DATA
x db 10 dup ("?")
y db 10 dup ("?")
.CODE
MOV AH,1
INT 21H
mov si,offset x
mov di,offset y
mov [si],al
cmp si,0
ja l1
jmp l2
l1 : mov al , 1
mov [di],al
jmp l3
l2 : mov ah , 0
mov y[di] , al
jmp l3
l3 :
MOV AH, 2
mov dl,al
INT 21H
cmp si,10
je l4
inc si
inc di
l4 :
.EXIT
END
The list of problems is long. Check out these comments and try to see why the error exists.
<<<< add label for a 10-time repeat
MOV AH,1
INT 21H
mov si,offset x <<<< move higher up for 1-time execution
mov di,offset y <<<< move higher up for 1-time execution
mov [si],al
cmp si,0 <<<< the byte to compare is in AL
ja l1 <<<< requires a SIGNED conditional, use JGE
jmp l2 <<<< reverse condition and drop this jump
l1 : mov al , 1
mov [di],al
jmp l3
l2 : mov ah , 0 <<<< should be AL
mov y[di] , al <<<< DI already refers to the y-array, use just [DI]
jmp l3 <<<< redundant
l3 :
MOV AH, 2
mov dl,al
INT 21H
cmp si,10 <<<< 10 is wrong
je l4
inc si <<<< move above checking iterator
inc di <<<< move above checking iterator
<<<< needs jumping back in order to repeat
l4 :
Next code, just like yours, inputs a single character from the keyboard and treats its ASCII code as the byte you want to store in the x array. For negative bytes you should input extended ASCII's. Use the Alt followed by a number up to 255.
.CODE
xor bx, bx
again:
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
mov x[bx], al
mov ah, 255
shl ax, 1
not ah
mov y[bx], ah ; 1 for positive, 0 for negative
inc bx
cmp bx, 10
jb again
.EXIT

Two async software UARTs return unexpected repeated characters

I was going to post this on codereview.stackexchange.com but the problem is this code does not work correctly.
I have an AT89C4051 processor which only has one hardware UART, however I will attach two UART-based devices to it of which one is my computer. The configuration across all devices is 9600,N,8,1 (9600bps, no parity, 8 data bits, 1 stop bit)
I attempted to create two software-based UARTs with machine-optimized code that can interface between the two devices, however the data I received on my computer is incorrect.
I was expecting 'ABCD' or 'abcd' to appear on the screen but all I received was 'DDDD'.
What can I do here to fix this problem without resorting to buying extra hardware?
;dual 9600bps channels
;RX1,TX1 = uart channel
;RX2,TX2 = uart channel
;start with uart configuration
org 0000h
ljmp uartcfg
;every 1/2 bit time execute function
org 000Bh
sjmp swuartint
SWCFG equ 20h ;serial config
;config for uart 1
SWRI bit 20h.0 ;data fully received if SWRI set
serrxslow bit 20h.2 ;bit flip-flop for receive. cpl 2x = 1 full bit time
SWTI bit 20h.1 ;data fully transmitted if SWTI set
sertxslow bit 20h.3 ;bit flip-flop for transmit. cpl 2x = 1 full bit time
;config for uart 2: same format
SWRI2 bit 20h.4
serrxslow2 bit 20h.6
SWTI2 bit 20h.5
sertxslow2 bit 20h.7
SWUARTNO bit 21h.0 ;current Software Uart Number
SWRNR bit 21h.1 ;Software Uart Receiver Not Ready
SWTMP equ 0Fh ;Temporary variable to pass indirect address value to register
SBUFR2 equ 0Eh ;Uart 2 received byte value
SBUFR equ 0Dh ;Uart 1 received byte value
SBUFT2 equ 0Ch ;Uart 2 sent byte value
SBUFT equ 0Bh ;Uart 1 sent byte value
swuartint:
;1/2 bit time detected.
;save registers
push PSW
push ACC
;set register bank RS1:RS0 = 1:1 or 1:0 depending on UART wanted
;so we have our own private set of R0-R7 variables for each UART
setb RS1
mov C,SWUARTNO
mov RS0,C
;Get bit from UART 2
mov C,RX2
jb RS0,nour1
mov C,RX1 ;Get bit from UART 1 if RS0 not set
nour1:
jb SWTI,extx
;Transmit routine is only used if transmit complete flag is NOT set.
cpl sertxslow
jnb sertxslow,extx
;Only do the real transmit work on full bit times
;save existing carry flag (it has received value)
push PSW
mov A,R2 ;R2=transmit counter to load
jnz tnz
;Counter=0: Load transmitted value to R3 through temporary variable
mov SWTMP,#R1
mov R3,SWTMP
;Set counter to 1 and clear C to output start bit (of 0)
inc A
clr C
sjmp extx1
tnz:
jnb ACC.3,tne
jnb ACC.0,tne
;Counter is 9 so set transmit complete flag
setb SWTI
clr A ;set counter to 0 and set C to output stop bit (of 1)
setb C
sjmp extx1
tne:
;Counter is between 1 and 8
;Save accumulator to R5 since push/pop wastes cycles
mov R5,A
mov A,R3 ;load accumulator with outgoing data
RRC A ;shift out one byte to C
mov R3,A ;save data
mov A,R5
inc A ;increment count
extx1:
;Use right transmit channel based on chosen UART number
jb RS0,nour2
mov TX1,C
sjmp extx2
nour2:
mov TX2,C
extx2:
;Save count
mov R2,A
;and load back receiver value C
pop PSW
extx:
mov A,R7 ;load receiving count
jnz rnz
;Counter=0. Store ready status
mov SWRNR,C
jc exrx
;increment counter only if start bit=0
inc A
clr serrxslow ;reset flip flop so we wait 1 bit time to get bit.
sjmp exrx
rnz:
cpl serrxslow
jb serrxslow,exrx
;Counter > 0, 1 bit time waited
jnb ACC.3,rne
jnb ACC.0,rne
;Counter = 9. Status = Stop bit. 1=complete. 0=fail.
mov SWRI,C
;Store data
mov SWTMP,R4
mov #R0,SWTMP
;Clear count
clr A
sjmp exrx
rne:
;Counter = 1 to 8.
;Load data same way as transmit routine
mov R6,A
mov A,R4
RRC A
mov R4,A
mov A,R6
inc A ;increment count
exrx:
mov R7,A ;save count to receive count variable
;Don't switch UARTs when in the middle of a bit time
jnb sertxslow,nextuart
;Don't switch UARTs if receiver has data to process
jnb SWRNR,nextuart
;Don't switch UARTs if transmitter has data to process
jnb SWTI,nextuart
;Switch UART
cpl SWUARTNO
;Flip nibbles in configuration as each nibble
;belongs to its own UART
mov A,SWCFG
swap A
mov SWCFG,A
nextuart:
;restore registers and exit
pop ACC
pop PSW
reti
uartcfg:
setb RS1
setb RS0
mov R0,#SBUFR2 ;If RS1=RS0=1, #R0 = contents of SBUFR2
mov R1,#SBUFT2 ;If RS1=RS0=1, #R1 = contents of SBUFT2
clr RS0
mov R0,#SBUFR ;If RS1=1 and RS0=0, #R0 = contents of SBUFR
mov R1,#SBUFT ;If RS1=1 and RS0=0, #R1 = contents of SBUFT
clr RS1 ;Restore register bank (RS1=0, RS0=0)
mov SWCFG,#22h ;Set transmit complete to both UARTs at once
mov TH0,#0A0h ;Value = 256-(((crystal/baud)/12)/2) = 9.6kbps 1/2 bit rate
mov TL0,#0A0h
mov TMOD,#22h ;8-bit timers auto reload
mov SP,#50h ;get stack pointer away from our work
setb TR0 ;enable timer
mov IE,#082h ;enable Timer 0 interrupt
ljmp startapp ;go to program
;serial port 1
;plugged into computer for data testing
RX1 equ P3.0
TX1 equ P3.1
;serial port 2
RX2 equ P3.3
TX2 equ P1.2
startapp:
; Trying to output 'ABCD' or 'abcd' but all I get is 'DDDD'
mov SBUFT,#0h ;Set character for UART 1
clr SWTI ;clear complete flag
jnb SWTI,$ ;stall until character transmitted
mov SBUFT,#'A' ;repeat...
clr SWTI
jnb SWTI,$
mov SBUFT,#'B'
clr SWTI
jnb SWTI,$
mov SBUFT,#'C'
clr SWTI
jnb SWTI,$
mov SBUFT,#'D'
clr SWTI
jnb SWTI,$
mov SBUFT2,#0h ;Set character for UART 2
clr SWTI2 ;clear complete flag
jnb SWTI2,$ ;stall until character transmitted
mov SBUFT2,#'a' ;repeat...
clr SWTI2
jnb SWTI2,$
mov SBUFT2,#'b'
clr SWTI2
jnb SWTI2,$
mov SBUFT2,#'c'
clr SWTI2
jnb SWTI2,$
mov SBUFT2,#'d'
clr SWTI2
jnb SWTI2,$
sjmp $

x86 real mode: move data from one array to another

Here is my code:
data segment
gio db 1,2,3,4,5,6
ricxvi db 1
jami db 0
x db ?
ends
stack segment
db 128 dup(0)
ends
code segment
start:
MOV AX,DATA
MOV DS,AX
mov cx, 6
lea si, gio
mov ah, 0
n1:
mov al, [si]
cmp ricxvi, 3
je n2
jmp n3
n2:
add jami, al
mov ricxvi, 1
jmp n4
n3:
add ricxvi, 1
push ax
n4:
add si, 1
add di, 1
loop n1
mov ricxvi, 1
mov ax, 0
mov cx, 6
lea si, gio
n5:
cmp ricxvi, 3
je n6
jmp n7
n6:
mov ricxvi, 1
add si, 1
loop n5
n7:
pop [si]
add si, 1
loop n5
mov ax, 4c00h
int 21h
ends
end start
I have a array named gio And I'm trying to reverse this array but leave every 3th element on its position. Meaning I want to get the output like this 5,4,3,2,1,6 but As I inspect variables, in array I have 5,4,2,1,B8. I have noticed that when program first hits pop [si] whole array changes, exploring variables shows me that its 5, NULL, 3, 4, 5, 6 should it not be 5,2,3,4,5,6? I'm using emu8086. Question may sound silly as I'm new with assembly. Thanks.
There are three errors :
You are poping two bytes into [si] but you only need one byte. The solution is to pop two bytes into a register and move one byte into [si].
Under label n6 you got loop n5, but when cx becomes zero the loop doesn't jump and the block n7 is executed when it shouldn't.
You forgot to increase the "3" counter under label n7.
Here are the fixes :
n6:
mov ricxvi, 1
add si, 1
loop n5
jmp finale ;◄■■ SKIP NEXT BLOCK WHEN CX=0.
n7:
add ricxvi, 1 ;◄■■ INCREASE THE "3" COUNTER.
pop ax ;◄■■ POP TWO BYTES.
mov [si], al ;◄■■ USE ONE BYTE ONLY.
add si, 1
loop n5
finale: ;◄■■ END LABEL.
mov ax, 4c00h
int 21h

Counter not working after jumps - assembly language

For some reason, when I switch to mouse input switch back to keyboard input for my program, increasing and decreasing the counter has no effect. It works perfectly in the first loop where we input characters.
Here is the program, any advice?
Look at whatspeed jump for reference after mousetime jump.
CX counter is not updating or something along those lines. (I do not know if the counter is not updating or weather there is a problem occuring in comparing CX after I switch from mousetime to keytime . )
CLEAR MACRO
MOV AX,0600H
MOV BH,07
MOV CX,0000
MOV DX,184FH
INT 10H
ENDM
CURSOR MACRO Col, Row
MOV AH,02
MOV BH,00
MOV DL,Col
MOV DH,Row
INT 10H
ENDM
DISP MACRO MES
MOV AH,09
MOV DX,OFFSET MES
INT 21H
ENDM
CLEARLINE MACRO ROW
CURSOR 00,ROW
DISP SPACES
ENDM
ALWAYSONSCREENINFO MACRO
CURSOR 16,00
DISP TITLE1
CURSOR 50,00
DISP NAMES1
CURSOR 54,01
DISP NAMES2
CURSOR 33,7
DISP MENU
CURSOR 24,9
DISP OPTION1
CURSOR 24,10
DISP OPTION2
CURSOR 22,11
DISP DASHES
CURSOR 18,12
DISP MOUSEMENU
CURSOR 14,13
DISP OPTION3
CURSOR 8,14
DISP OPTION4
CURSOR 13,15
DISP CHARMENU
CURSOR 21,16
DISP KILL
ENDM
.MODEL SMALL ; RUN THE PROGRAM IN DIMENSIONS 79x24
.STACK 64H
.DATA
TITLE1 DB 'MICROPROCESSOR - EENG410','$'
NAMES1 DB 'name1 & name2','$'
NAMES2 DB 'std1 std2','$'
MENU DB 'MENU','$'
OPTION1 DB '1. Press "U" to Speed up the motor','$'
OPTION2 DB '2. Press "D" to Slow Down the motor','$'
OPTION3 DB '1. Right click the mouse to turn motor direction to clockwise','$'
OPTION4 DB '2. Left click the mouse to turn the motor direction to anti-clockwise','$'
DASHES DB '----------------------------------------','$'
MOUSEMENU DB '(Press M to switch to the mouse options)','$'
CHARMENU DB '(Press the scroll button to switch back to fist 2 options)','$'
SPEEDUP DB 'DC motor is speeding up ','$'
SLOWDOWN DB 'DC motor is slowing down','$'
RIGHT DB 'DC motor will now rotate clockwise','$'
LEFT DB 'DC motor will now rotate anti-clockwise','$'
KILL DB '-----To exit the program, press "E"-----','$'
PROGRAMEND1 DB 'Thank you for using our program','$'
PROGRAMEND2 DB 'The program has been terminated','$'
SPACES DB ' ','$'
TRY DB 'Please try again','$'
SPEEDNOW DB 'Speed:','$'
DIRECTION DB 'Motor Direction:','$'
CLOCK DB 'Right','$'
COUNTER DB 'Left ','$'
N1 DB '1','$'
N2 DB '2','$'
N3 DB '3','$'
N4 DB '4','$'
N5 DB '5','$'
N6 DB '6','$'
N7 DB '7','$'
MAXSPEED DB 'Max speed is 7','$'
MINSPEED DB 'Min speed is 1','$'
.CODE
MAIN: MOV AX,#DATA
MOV DS, AX
CLEAR
ALWAYSONSCREENINFO
MOV CX,1
CURSOR 28,21
DISP SPEEDNOW
CURSOR 35,21
DISP N1
CURSOR 22,22
DISP DIRECTION
CURSOR 39,22
DISP CLOCK
MOV CX,1
L0: MOV AH,00 ;LOOP START
INT 16H
CMP AL,' '
JE SPACED
CMP AL,'U'
JE FASTER
CMP AL,'u'
JE FASTER
CMP AL,'D'
JE SLOWER
CMP AL,'d'
JE SLOWER
CMP AL,'M'
JE MOUSETIME
CMP AL,'m'
JE MOUSETIME
CMP AL,'E'
JE EXIT
CMP AL,'e'
JE EXIT
JNE TRYAGAINKEY
A1: MOV AX,03
INT 33H
CMP BX,0
JE A1
CMP BX,1 ;MOUSE LEFT
JE MRIGHT
CMP BX,2 ;MOUSE RIGHT
JE MLEFT
CMP BX,3
JE KEYTIME
SPACED: CLEARLINE 19
JMP L0
FASTER: CLEARLINE 19
CURSOR 27,19
DISP SPEEDUP
JMP INCREASE
SLOWER: CLEARLINE 19
CURSOR 27,19
DISP SLOWDOWN
JMP DECREASE
MOUSETIME: JMP A1
KEYTIME: JMP L0
MRIGHT: CLEARLINE 19
CURSOR 18,19
DISP RIGHT
JMP TRIGHT
MLEFT: CLEARLINE 19
CURSOR 18,19
DISP LEFT
JMP TLEFT
TRYAGAINKEY: CLEARLINE 19
CURSOR 28,19
DISP TRY
JMP L0
INCREASE: CMP CX,7
JE CANNOTINCREASESPEED
INC CX
JMP WHATSPEED
DECREASE: CMP CX,1
JE CANNOTDECREASESPEED
DEC CX
JMP WHATSPEED
TRIGHT: CURSOR 39,22
DISP CLOCK
JMP A1
TLEFT: CURSOR 39,22
DISP COUNTER
JMP A1
CANNOTINCREASESPEED: CLEARLINE 19
CURSOR 27,19
DISP MAXSPEED
JMP L0
CANNOTDECREASESPEED: CLEARLINE 19
CURSOR 27,19
DISP MINSPEED
JMP L0
WHATSPEED: CMP CX,1
JE N11
CMP CX,2
JE N22
CMP CX,3
JE N33
CMP CX,4
JE N44
CMP CX,5
JE N55
CMP CX,6
JE N66
CMP CX,7
JE N77
N11: CURSOR 35,21
DISP N1
JMP L0
N22: CURSOR 35,21
DISP N2
JMP L0
N33: CURSOR 35,21
DISP N3
JMP L0
N44: CURSOR 35,21
DISP N4
JMP L0
N55: CURSOR 35,21
DISP N5
JMP L0
N66: CURSOR 35,21
DISP N6
JMP L0
N77: CURSOR 35,21
DISP N7
JMP L0
EXIT: CLEAR
CURSOR 21,12
DISP PROGRAMEND1
CURSOR 21,13
DISP PROGRAMEND2
MOV AH, 4CH
INT 21H
END MAIN
The fault is caused because the mouse interrupt 33h function AX=0003h returns the mouse position in CX and DX.
This overwrites your "counter" in register CX.
It is always a dangerous game to keep values in registers throughout a program. Better to have a memory variable location.
You could also try PUSH CX before executing the mouse functions and POP CX after, but your program structure and flow might not be conducive to that (I have not followed it fully).
Also, the reason why your program does not recover from (in your context) the absurd value of CX is because of the test instruction you used. For example here
INCREASE: CMP CX,7
JE CANNOTINCREASESPEED
you must always be cautious and trap any value that is out of range (even if you think it won't be)
JGE CANNOTINCREASESPEED
Also with
CANNOTINCREASESPEED: MOV CX,7 ;clamp the value
...

Resources