Assembly 如果数字大于32767,则打印到LED端口199
所以,我创建了一个程序来测量步进电机转动的度数。我们必须将度数精确到十分之一度,即如果电机转动了141.75度,我们必须打印出14175,因为LED没有小数点 我遇到了一个障碍,当我试图打印大于327.67的任何度数时,LED会显示负数,因为微处理器会自动表示有符号的数字。例如,348.75应该作为34875打印到LED显示屏上,但它使用代表34875的二进制值的负补码,即-31786。有人知道怎么在这个LED显示屏上显示36000吗 我的代码的逻辑如下: 每向右移动一次,SI都会增加 每向左移动一次,DI都会增加 为了找到度数,我移动并比较它们,看看它们是否不在开始处 第二,我从另一个中减去一个,取决于哪个更大。如果DI较大,则向左移动或顺时针移动,然后加58跳到与需要打印的度数对应的值Assembly 如果数字大于32767,则打印到LED端口199,assembly,x86-16,unsigned,signed,emu8086,Assembly,X86 16,Unsigned,Signed,Emu8086,所以,我创建了一个程序来测量步进电机转动的度数。我们必须将度数精确到十分之一度,即如果电机转动了141.75度,我们必须打印出14175,因为LED没有小数点 我遇到了一个障碍,当我试图打印大于327.67的任何度数时,LED会显示负数,因为微处理器会自动表示有符号的数字。例如,348.75应该作为34875打印到LED显示屏上,但它使用代表34875的二进制值的负补码,即-31786。有人知道怎么在这个LED显示屏上显示36000吗 我的代码的逻辑如下: 每向右移动一次,SI都会增加 每向左移
#start=stepper_motor.exe#
#start=led_display.exe#
data segment
ANGLE dw 0, 1125, 2250, 3375, 4500, 5625, 6750, 7875, 9000, 10125,
dw 11250, 12375, 13500, 14625, 15750, 16875, 18000, 019125,
dw 020250, 021375, 022500, 023625, 024750, 025875, 027000, 028125,
dw 029250, 030375, 031500, 032625, 033750, 034875, 036000
; words for the menu
menu db "MENU", 13, 10
db " ", 13, 10
db " 1- Reset", 13, 10
db " 2- Select clockwise or counterclockwise", 13, 10
db " 3- Select continuous or keyboard input", 13, 10
db " 4- Turn", 13, 10
db " >- Turn Right", 13, 10
db " <- Turn Left", 13, 10
db " ", 13, 10
db " Q-QUIT", 13, 10
db " ",13,10
db " ",13,10
db " ENTER CHOICE: $"
tcw db "Turning clockwise $"
tccw db "Turning counterclockwise $"
tcont db "Turn continuously $"
tman db "Turn manually $"
pkey db "press any key...$"
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
setup:
mov si, 0 ;index for left move
mov di, 0 ;index for right move
call blubox ;sets up the screen with menu
MOV AL, 02H ;TURN MIDDLE MAGNET ON
OUT 7, AL
functionator:
CALL KEYPRESS ;check if key has been pressed
CALL MOUSEGRAB
JMP functionator
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHECKS THE DEGREES OF THE STEPPER;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CHECKDEGREES PROC NEAR
PUSH SI
PUSH DI
CMP SI, DI ;CHECKS IF 0 DEGREES
JE ZERO
JG LEFTDEGREE ;STEPPER IS ON LEFT HALF, CHECK DEGREES THERE
SUB DI, SI
SHL DI, 1
MOV BX, 64
SUB BX, DI
MOV DI, BX
MOV AX, ANGLE[DI]
OUT 199, AX
JMP DONEDEGREE
LEFTDEGREE:
SUB SI, DI
SHL SI,1
MOV AX, ANGLE[SI]
OUT 199, AX
JMP DONEDEGREE
ZERO:
XOR AX, AX
OUT 199, AX
DONEDEGREE:
POP DI
POP SI
RET
CHECKDEGREES ENDP
;;;;;;;;;;;;;;;;;;;;;;
;RESTARTS THE STEPPER;
;;;;;;;;;;;;;;;;;;;;;;
RESETIT PROC NEAR
push ax
push bx
push cx
resetstep:
CMP SI, DI
JE DONERESET
JG LEFTCOMMAND
RIGHTCOMMAND:
SUB DI, SI
MOV CX, DI
GORIGHT1:
CALL DELAY
CALL MOVERIGHT
CMP CX, 1
JE DONERESET
DEC CX
JMP GORIGHT1
JMP DONERESET
LEFTCOMMAND:
SUB SI, DI
MOV CX, SI
GOLEFT1:
CALL DELAY
CALL MOVELEFT
CMP CX, 1
JE DONERESET
DEC CX
JMP GOLEFT1
DONERESET:
MOV SI, 0H
MOV DI, 0H
POP CX
POP BX
POP AX
RET
RESETIT ENDP
;;;;;;;;;;;;;;;;;;;;;
;creates a delay;;;;;
;;;;;;;;;;;;;;;;;;;;;
delay proc near
mov ax, 5
countit:
cmp ax, 0
je donedelay
dec ax
jmp countit
donedelay:
ret
delay endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;moves the stepper to the LEFT;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVERIGHT PROC NEAR
IN AL, 7
CMP AL, 81H ;IF RIGHTMOST MAGNET IS ON, TURN
JE RIGHT2 ;TWO LEFTMOST MAGNETS ON
CMP AL, 82H ;IF MIDDLE MAGNET IS ON,
JE RIGHT1 ;TURN ON TWO RIGHTMOST MAGNETS
CMP AL, 83H ;IF TWO RIGHTMOST MAGNETS ARE ON,
JE RIGHT3 ;TURN ON THE RIGHTMOST MAGNET
CMP AL, 84H ;IF ONE LEFTMOST MAGNET IS ON,
JE RIGHT2 ;TURN ON TWO LEFTMOST MAGNETS
CMP AL, 86H ;IF TWO LEFTMOST MAGNETS ARE ON,
JE RIGHT4 ;TURN MIDDLE MAGNET ON
RIGHT1:
MOV AL, 03H ;TURN ON THE TWO RIGHT MAGNETS
OUT 7, AL ;FOR A HALFSTEP TO THE RIGHT
JMP DONERIGHT
RIGHT2:
MOV AL, 06H ;TURN THE TWO LEFTMOST MAGNETS ON
OUT 7, AL ;FOR A HALFSTEP TO THE RIGHT
JMP DONERIGHT
RIGHT3:
MOV AL, 01H ;TURN RIGHTMOST MAGNET ON
OUT 7, AL ;FOR FULL STEP TO RIGHT
JMP DONERIGHT
RIGHT4:
MOV AL, 02H ;TURN MIDDLE MAGNET ON FOR
OUT 7, AL ;FULL STEP TO RIGHT
DONERIGHT:
CMP SI, 20H
JE RESETSI
inc SI
JMP FINALRIGHT
RESETSI:
MOV SI, 1H
FINALRIGHT:
CALL checkdegrees
RET
MOVERIGHT ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;moves the stepper to the right;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVELEFT PROC NEAR
IN AL, 7
CMP AL, 86H ;IF TWO LEFT MAGNETS ARE ON,
JE LEFT2 ;TURN LEFTMOST MAGNET ON
CMP AL, 84H ;IF ONE LEFTMOST MAGNET IS ON,
JE LEFT3 ;TURN ON TWO RIGHTMOST MAGNETS ON
CMP AL, 83H ;IF TWO RIGHTMOST MAGNETS ARE ON,
JE LEFT4 ;TURN ON MIDDLE MAGNET
CMP AL, 82H ;IF MIDDLE MAGNET IS ON,
JE LEFT1 ;TURN ON TWO LEFTMOST MAGNETS
CMP AL, 81H ;IF RIGHTMOST MAGNET IS ON, TURN
JE LEFT3 ;TWO RIGHTMOST MAGNETS
LEFT1:
MOV AL, 06H ;TURN ON THE TWO LEFT MOTORS
OUT 7, AL ;FOR A HALFSTEP TO THE LEFT
JMP DONELEFT
LEFT2:
MOV AL, 04H ;TURN THE LEFTMOST MAGNET ON
OUT 7, AL
JMP DONELEFT
LEFT3:
MOV AL, 03H ;TURN TWO RIGHTMOST MAGNETS ON
OUT 7, AL
JMP DONELEFT
LEFT4:
MOV AL, 02H ;TURN MIDDLE MAGNET ON
OUT 7, AL
DONELEFT:
CMP DI, 20H
JE RESETDI ;when
inc DI
JMP FINALLEFT
RESETDI:
MOV DI, 1H
FINALleft:
CALL CHECKDEGREES
RET
MOVELEFT ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHECKS IF MOUSE HAS BEEN PRESSED;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOUSEGRAB PROC NEAR
PUSH CX
PUSH BX
MOV AX, 01H ;DISPLAY CURSOR
INT 33H
MOV AX, 03H ;FIND OUT THE BUTTON PRESS
INT 33H
CMP BX, 01H ;IF MOUSE NOT PRESSED, JUMP OUT
JE GOMOUSE
POP BX
POP CX
JMP MOUSEDONE
GOMOUSE:
CMP DX, 20H
JL MOUSEDONE
CMP DX, 28H
JL RESETMOUSE
CMP DX, 30H
JL DIRECTMOUSE
CMP DX, 38H
JL INPUTMOUSE
CMP DX, 40H
JL TURNMOUSE
CMP DX, 48H
JL RIGHTMOUSE
CMP DX, 50H
JL LEFTMOUSE
CMP DX, 58H
JG MOUSEDONE
DIRECTMOUSE:
POP BX
POP CX
CALL DIRECT
JMP MOUSEDONE
INPUTMOUSE:
POP BX
POP CX
CALL ENTER
JMP MOUSEDONE
TURNMOUSE:
POP BX
POP CX
CMP BH, 1
JE CONT_TURN_MOUSE
JMP MOUSEDONE
RIGHTMOUSE:
POP BX
POP CX
CALL MOVERIGHT
JMP MOUSEDONE
LEFTMOUSE:
POP BX
POP CX
CALL MOVELEFT
JMP MOUSEDONE
CONT_TURN_MOUSE:
CMP BL, 1
JE TURNCLOCK_MOUSE
CALL TURNCCW
JMP MOUSEDONE
TURNCLOCK_MOUSE:
CALL TURNCW
JMP MOUSEDONE
RESETMOUSE:
POP BX
POP CX
CALL RESETIT
MOUSEDONE:
RET
MOUSEGRAB ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHECKS TO SEE IF KEY HAS BEEN PRESSED;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
KEYPRESS PROC NEAR
MOV AH, 1H ;CHECKS IF KEY IS IN BUFFER
INT 16H
JZ DONE
mov ah, 0h ;MOVES PRESS FROM BUFFER
int 16h
CMP AH, 10H ;IF Q, THEN QUIT
JE FINISH
CMP AL, 34H ;if 4, turn (only if continuous)
JE TURNIT
CMP AH, 4BH ;if <- then move left
JE GOLEFT
CMP AH, 4DH ;if -> then move right
JE GORIGHT
CMP AL, 31H ;if 1 then reset
JE GORESET
CMP AL, 32H ;if 2, select clockwise or counter
JE DIRECTION
CMP AL, 33H ;if 3, select continuous or manual
JE INPUT
JMP DONE
INPUT:
CALL ENTER
JMP DONE
TURNIT:
CMP BH, 1
JE CONTINUOUSTURN
JMP DONE
DIRECTION:
CALL DIRECT
JMP DONE
GOLEFT:
CALL MOVELEFT
JMP DONE
GORIGHT:
CALL MOVERIGHT
JMP DONE
GORESET:
CALL RESETIT
JMP DONE
CONTINUOUSTURN:
CMP BL, 1
JE TURNCLOCK
CALL TURNCCW
JMP DONE
TURNCLOCK:
CALL TURNCW
DONE:
RET
KEYPRESS ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;TURNS CONTINUOUSLY CLOCKWISE;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TURNCW PROC NEAR
TURNCWLOOP:
CALL MOVELEFT
CALL DELAY
MOV AH, 1H ;CHECKS IF KEY IS IN BUFFER
INT 16H
JNZ doneturning
PUSH CX
PUSH BX
MOV AX, 03H ;FIND OUT THE MOUSE PRESS
INT 33H
CMP BX, 01H ;IF MOUSE NOT PRESSED, JUMP OUT
POP BX
POP CX
JNE TURNCWLOOP
doneturning:
RET
TURNCW ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;TURNS CONTINUOUSLY COUNTERCLOCKWISE;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TURNCCW PROC NEAR
TURNCCWLOOP:
CALL MOVERIGHT
CALL DELAY
MOV AH, 1H ;CHECKS IF KEY IS IN BUFFER
INT 16H
JNZ doneturningccw
PUSH CX
PUSH BX
MOV AX, 03H ;FIND OUT THE MOUSE PRESS
INT 33H
CMP BX, 01H ;IF MOUSE NOT PRESSED, JUMP OUT
POP BX
POP CX
JNE TURNCCWLOOP
doneturningccw:
RET
TURNCCW ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;DETERMINES IF CONTINUOUS OR MANUAL;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ENTER PROC NEAR
PUSH BX
MOV AH, 02H ;moves cursor to letter
MOV BH, 0H ;after "Turn"
MOV DH, 11H
MOV DL, 5
INT 10H
MOV AH, 08H ;OBTAIN THE LETTER IN AL
MOV BH, 0H
INT 10H
MOV AH, 02H ;moves cursor to print new
MOV BH, 0H ;string
MOV DH, 11H
MOV DL, 0H
INT 10H
POP BX
CMP AL, 'c' ;CHECK IF CONTINOUS
JE MANTURN
MOV AH, 09H ;print "turn continuously"
MOV DX, OFFSET tcont
INT 21H
MOV BH, 1 ;index for moving motor
JMP DONEENTER
MANTURN:
MOV AH, 09H
MOV DX, OFFSET tman ;print "turn manual"
INT 21H
MOV BH, 0
doneenter:
RET
ENTER ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHECKS CURRENT DIRECTION THEN CHOOSES THE NEW ONE;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DIRECT PROC NEAR
PUSH BX
MOV AH, 02H ;moves cursor to letter
MOV BH, 0H ;after "C" in either clockwise
MOV DH, 10H ;or counterclockwise
MOV DL, 9
INT 10H
MOV AH, 08H ;OBTAIN THE LETTER IN AL
MOV BH, 0H
INT 10H
MOV AH, 02H ;moves cursor to print new
MOV BH, 0H ;string
MOV DH, 10H
MOV DL, 0H
INT 10H
POP BX
CMP AL, 'l' ;CHECK IF CLOCKWISE
JE CCWCOUNT
MOV AH, 09H ;print "turning clockwise"
MOV DX, OFFSET tcw
INT 21H
MOV BL, 1 ;index for moving motor
JMP DONEDIRECT
CCWCOUNT:
MOV AH, 09H
MOV DX, OFFSET tccw ;print "turning ccw"
INT 21H
MOV BL, 0
donedirect:
ret
DIRECT ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CREATES BLUE BACKGROUND;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BLUBOX PROC NEAR
MOV AH, 7H ;creates a blue background
MOV AL, 0H
MOV BH, 1EH
MOV CH, 0H
MOV CL, 0H
MOV DH, 24
MOV DL, 79
INT 10H
MOV AH, 02H ;moves cursor for menu
MOV BH, 0H
MOV DH, 2H
MOV DL, 25H
INT 10H
MOV AH, 09 ;PRINTS "MENU"
MOV DX, OFFSET MENU
INT 21H
RET
BLUBOX ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;clears the screen;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
CLEARSCREEN PROC NEAR
MOV AH, 06H ;clear screen
MOV AL, 0
MOV BH, 7
MOV CH, 0
MOV CL, 0
MOV DH, 24
MOV DL, 79
INT 10H
MOV AH, 02H ;moves the cursor
MOV BH, 0H
MOV DH, 0H
MOV DL, 0H
INT 10H
RET
CLEARSCREEN ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;program is finished;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FINISH:
call clearscreen
lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
mov ah, 1
int 21h
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start ; set entry point and stop the assembler.
16位带符号整数只能保存-32768到32767之间的值。除了使用其他编码(如excess-n)外,无法表示较大的有符号值 如果您不需要负角度,那么只需使用无符号类型,您将获得两倍的范围。否则,您将不得不使用32位int-dd,如果可能的话,删除旧的8086
然而,你测量的是百分之一度,而不是前面提到的十分之一度,所以你失去了10倍的范围。如果您真正想要的是1/10度的分辨率,那么使用16位int,您将能够存储从-3276.8°到3276.7°的角度,只需将输入减少10倍没有人会为您读取这么长的代码。你应该写一个SSCCE,最好地展示你的问题