As a beginner in PIC programming I try to understand an existing and running code. In that code I find.
movf c10m,w ;Read 10th of min count
movwf bcd_in ;Set counter code here
Where to find the destination flag d?
I understand that data of c10m goes into w with movf. The behaviour of movf depends on a destination flag d. But I can not find the whereabout of the flag and how to manipulate.
The direction bit is normally decided by the second operand. This is described but not very clearly in the microchip manual (it uses FSR which is an indrection register). The instruction means move file the contents of the file register. If d=0, the destination is W; if d=1, it is the register itself.
The format of the command is
MOVF file,d
where d=0 or 1 but most assemblers will accept W in place of d. Note that it does not check the contents of W. It is not that complex. It does not matter what is in W, it will get overwritten.
; d Before After
; W TMR0 Z W TMR0 Z
MOVF TMR0,W ; 0 ?? 25 ? 25 25 0
MOVF TMR0,W ; 0 ?? 00 ? 00 00 1
MOVF TMR0,0 ; 0 ?? 25 ? 25 25 0 same as MOVF TMR0,W
MOVF TMR0,1 ; 1 ?? 25 ? ?? 25 0
MOVF TMR0,1 ; 1 ?? 00 ? ?? 00 1
Moving a file register to itself will cause the zero flag to be set if the value is zero.
Related
I am trying to add the first 3 digits and last 3 digits of the series of numbers and subtracting the second result with the first. I will have to use the load byte and store byte commands. But when I use sb, I get the wrong answer.
My code is as follows (in MIPS assembly language):
.data
D1: .byte 1,7,2,0,0,3
D2: .byte 0
.text
.globl main
main: la $t0,D1
la $t9,D2
lb $t1,0($t0)
lb $t2,4($t0)
add $t3,$t1,$t2
lb $t4,8($t0)
add $t3,$t3,$t4
lb $t5,16($t0)
lb $t6,20($t0)
lb $t7,24($t0)
add $t8,$t5,$t6
add $t8,$t8,$t7
sub $t8,$t8,$t3
sb $t8,0($t9)
li $v0,10
syscall
Until sub $t8,$t8,$t3 I get the correct answer -7 that is stored in $t8 but when I use sb, the answer is 249. I am unable to figure out why that is.
The number -7(signed) in binary is :
11111111 11111111 11111111 11111001
And number 249(signed) is :
00000000 00000000 00000000 11111001
sb (save byte) , saves just one byte(8LS bits). This is why you'r getting 249 instead of -7.
After sb you can do :
lui $t8, 65535 # this will change the first 16 bits from 0 to 1
then add the correct number to $t8 to take the wished output.
However i do not know what you're trying to accomplish.
I am using DosBox and I have a string read in from the buffer using an interrupt. I know where the first character is stored in memory, how do I increment to the next character?
0100 mov ah, 0a
0102 mov dx, 111
0105 int 21
0107 mov dl, [113] ;first character here
010b mov ah, 02
010d int 21
010f int 20
0111 db 0f
The question is how do I increment to the next character in the string? If I input the string "Hello" and then use inc dl it simply gives me the letter "I" instead of "e".
You need to pick a register to point at the current character. Once you have this there are instructions to advance your pointer as well as instructions to read the byte the pointer is pointing to.
Since you don't know how many characters will be read by the user input function, and you want this function to work with any input value, you'll need some sort of loop so you only print as many characters as have been read, although if you wanted to make it simple, you could make it only print the first 3 characters regardless of what was typed in. I'm going to assume you want to print out exactly what was typed by the user.
A good way to tackle this is to use the LOOP instruction which repeats (jumps into) the loop body by the count that has been placed into the CX register. Since the user input function gives us the character count, all we have to do is read that into the lower portion of the CX register (CL) for loop initialization. We'll also need a pointer to point to the current character. Once in the loop body, we'll just read whatever character is at our "current character" pointer and then call the DOS character-print function to output it to the console. Then we can advance the pointer and LOOP until all characters have been done. Note that each time the LOOP instruction is encountered, CX is decremented until it reaches zero. Once it is zero, LOOP no longer jumps back into the body and simply advances to the instruction following the LOOP.
NOTE: If you don't output a CRLF after reading the user input, there will be no line feed and the new output will overwrite where the input was read on the console. Effectively it will look like nothing happened.
Here's your modified sample:
0100 MOV AH,0A
0102 MOV DX,0123
0105 INT 21 ;input string using buffer at 0123
0107 MOV DX,0120
010A MOV AH,09
010C INT 21 ;output CRLF sequence first
010E MOV SI,0124 ;point SI at byte containing chars read
0111 XOR CX,CX ;CX = 0
0113 MOV CL,[SI] ;CX = chars_read
0115 INC SI ;mov SI to next char to display
0116 MOV DL,[SI] ;DL = character SI is pointing at
0118 MOV AH,02
011A INT 21 ;display character
011C LOOP 0115 ;loop back to INC instruction until no more chars left
011E INT 20 ;exit
0120 DB 0D ;CR
0121 DB 0A ;LF
0122 DB 24 ;"$" DOS string terminator
0123 DB 20 ;buffer start; max characters = 32
0124 DB 00 ; chars read goes here
0125 DB 00 ; input chars are read here
I want to implement a routine that calculates the sum of all natural numbers from 1 to n. n is a variable stored in RAM. The result has to be stored in a two-byte variable in RAM, too. I'm very new in assembly programming so I'm having a hard time trying to figure out the algorithm to achieve this. So far, I've done this:
.DSEG
.ORG 0x100
n: .BYTE l_n
result: .BYTE l_result
.CSEG
.ORG 0x100
SUM:
LDI XL, n ;the direction of n is stored in XL
LD R16, X ;now r16=n
LDI XL, LOW(result)
LDI XH, HIGH(result) ;X points to result
CLC ;in case C is full with trash
LDI R17, 0x0 ;R17 = 0
LDI R18, 0x1 ;R18 = 1
CALL LOOP
LDI R16,0
LDI R17,0
ADC R16, R17 ;if C is on when the loop finishes, then it has to be summed as well
ST X, R16
RET ;returns to the program that called the routine
I did the initialization of R17 and R18 because I thought that the subroutine LOOP should do something like increasing this numbers one by one until doing it n times. The thing that is complicating me the most is the fact that the result has two bytes, while each number being summed consists of just one byte. I don't know how to deal with this. Any help will be appreciated.
what you need is
ADD R18,R24 //sumL += nL
ADC R19,R25 //sumH += nH + Carry
and for 2 bytes variable the max sum will be 65535 so for
1+2+3+...+n=n*(n+1)/2 <= 65535 then N <= 361 = 0x0169
1+2+3+...+361=361*362/2=65341
and code will looks like this:
//CPU: ATmega128A
.include "m128Adef.inc"
.DSEG
//.ORG 0x100
n: .BYTE 2 // define 2 bytes var
result: .BYTE 2 // define 2 bytes var
.CSEG
.ORG 0
RJMP boot
n0: .DW 0x0169 //init value for n=361 (max value for 2 byte result)
//in: N=R24:R25
//out: Sum=R18:R19
//calc sum 1 to n (n >=1 and n <=361)
//1+2+3+...+n=n*(n+1)/2 <= 65535 => n<=361= 0x0169
Sum1toN:
LDI R18,0x00 //sumL=0
LDI R19,0x00 //sumH=0
Lsum:
ADD R18,R24 //sumL + = nL
ADC R19,R25 //sumH += nH + C
SBIW R24,0x01 //n--
BRNE Lsum // n >0 ?
RET
boot:
CLR R1
OUT SREG,R1 //Clear all
//init stack pointer
LDI R28,LOW(RAMEND) //LDI R28,0xFF
LDI R29,HIGH(RAMEND) //LDI R28,0x10
OUT SPH,R29
OUT SPL,R28
//init
LDI ZL,LOW(n0<<1)
LDI ZH,HIGH(n0<<1)
LDI XL,LOW(n)
LDI XH,HIGH(n)
LDI R24,2
LDI R25,0
init:
LPM R0,Z+
ST X+,R0
SBIW R24,1
BRNE init
//calc:
LDS R24,n // LDS R24,0x0100
LDS R25,n+1 // LDS R25,0x0101
RCALL Sum1toN
STS result,R18
STS result+1,R19
main:
RJMP main
So, here in the following code, I am writing a code to sort numbers in ascending order.
start: nop
MVI B, 09 ; Initialize counter
LXI H, 2200H ;Initialize memory pointer
MVI C, 09H; Initialize counter 2
BACK: MOV A, M ;Get the number
INX H ;Increment memory pointer
CMP M; Compare number with next number
JC SKIP;If less, don't interchange
JZ SKIP; If equal, don't interchang
MOV D, M
MOV M, A
DCX H
MOV M, D
INX H ;Interchange two numbers
DCR C ; Decrement counter 2
JNZ BACK ;If not zero, repeat
DCR B ; Decrement counter 1
JNZ START
HLT ; Terminate program execution
This was that was taught in class.
When I try running the code in GNUSim, I get errors like :
1. Line 9: Undefined symbol.
2. Line 9: Invalid operand or symbol.Check whether operands start with a 0. Like a0H should be 0a0H.
Can somebody help?
In 8085 (js8085) I'd do it the next way (using bubble sort):
#begin 0100
#next 0100
MVI A 00
MVI B 00
MVI C 00
MVI D 00
MVI E 00
MVI H 00
MVI L 00
IN 00
out 00
DCR A
out 06
bubble: in 06
cmp c
jz finished
inr e
ldax b
mov h,a
ldax d
cmp h
jc change;
comprobation: in 00
cmp e
jz semi-fin
call bubble
semi-fin: inr c
mov a,c
mov e,c
call bubble
change: stax b
mov a,h
stax d
call comprobation
finished: hlt
In the port 00 you got the number of elements you have and the the elements themselves are starting from the position 0000 to the number of elements - 1.
I am trying to learn more about assembly and disassembly.
My goal is to modify the way a specific address is being written using a debugger (olly). Preferably by incrementing it by a number (20, 50, etc..) I can identify the address of the floating point number (in this case located at 33B7420C).
When I set a breakpoint on memory access write it brings me to 00809B2E which has the following assembly:
FSTP DWORD PTR DS:[ESI+1224]
What exactly is it doing in this address? I know that the FPU register has the number i'm looking for but not sure what all this address is doing.
The closest I come to googling is:
What does MOV EAX, DWORD PTR DS:[ESI] mean and what does it do?
A copy of the registers shows the following:
EAX 00000000
ECX 00A16E40 EZ.00A16E40
EDX FFFFFFFF
EBX 33B74578
ESP 0018FA90
EBP 00000000
ESI 33B72FE8
EDI 33B74578
EIP 00809B2E <EZ.Breakpoint for time>
C 0 ES 002B 32bit 0(FFFFFFFF)
P 0 CS 0023 32bit 0(FFFFFFFF)
A 0 SS 002B 32bit 0(FFFFFFFF)
Z 0 DS 002B 32bit 0(FFFFFFFF)
S 0 FS 0053 32bit 7EFDD000(FFF)
T 0 GS 002B 32bit 0(FFFFFFFF)
D 0
O 0 LastErr ERROR_SUCCESS (00000000)
EFL 00210202 (NO,NB,NE,A,NS,PO,GE,G)
ST0 valid 1150.0000000000000000
ST1 zero 0.0
ST2 zero 0.0
ST3 empty 64.951911926269531250
ST4 empty -13.250000000000000000
ST5 empty 64.951911926269531250
ST6 empty 64.951911926269531250
ST7 empty 0.0239995196461677551
3 2 1 0 E S P U O Z D I
FST 2927 Cond 0 0 0 1 Err 0 0 1 0 0 1 1 1 (LT)
FCW 027F Prec NEAR,53 Mask 1 1 1 1 1 1
Any help would be appreciated, Thanks!
FSTP stores a floating point number from the top of the floating-point register stack (ST0) to the designated memory region. Using the DWORD modifier means that a 32-bit float will be written. The P suffix indicates that the floating-point register stack will be popped after the operation.
So, in effect, this instruction puts 1150.0 (as a 32-bit float) at DS:[ESI+1224], then pops the register stack (which causes ST0 = 0.0, ST1 = 0.0, ST2 = <empty>, etc.).
It's storing ST0 (1150.0) in single-precision to your address. And popping said value from the FPU stack.
To add 50 (0x32 being hex for 50):
mov eax, dword[ds:esi+0x1224]
add eax, 0x32
mov dword[ds:esi+0x1224], eax