Understanding Subi Syntax for AVR Programming - avr

I've come across a certain piece of code that i'm not quite understanding and have been unable to find any information on it. It's a macro that takes in a register and then should display the result on the LCD.
The contents of the register being passed in should be a single digit number.
.macro do_lcd_rdata
mov lcd, #0
subi lcd, -'0'
rcall lcd_data
rcall lcd_wait
.endmacro
The part I am confused about is what subi lcd, -'0' this means. SUBI is subtract immediate but I am confused about what -'0' is.

-'0' is the negative of the ascii value of the character '0'. The operation is effectively adding 0x30 or 48 to the value in the register to turn it into the equivalent ascii character value of the digit.
For example, 6 - -'0' = 6 + 48 = 54 = '6'

Related

Understanding 8086 assembler debugger

I'm learning assembler and I need some help with understanding codes in the debugger, especially the marked part.
mov ax, a
mov bx, 4
I know how above instructions works, but in the debugger I have "2EA10301" and "BB0400".
What do they mean?
The first instruction moves variable a from data segment to the ax register, but in debugger I have cs:[0103].
What do mean these brackets and these numbers?
Thanks for any help.
The 2EA10301 and BB0400 numbers are the opcodes for the two instructions highlighted.
2E is Code Segment (CS) prefix and instructs the CPU to access memory with the CS segment instead of the default DS one.
A1 is the opcode for MOV AX, moffs16 and 0301 is the immediate 0103h in little endian, the address to read from.
So 2EA10301 is mov ax, cs:[103h].
The square brackets are the preferred way to denote a memory access through one the addressing mode but some assemblers support the confusing syntax without the brackets.
As this syntax is ambiguous and less standardised across different assemblers than the other, it is discouraged.
During the assembling the assembler keeps a location counter incremented for each byte emitted (each "section"/segment has its own counter, i.e. the counter is reset at the beginning of each "section").
This gives each variable an offset that is used to access it and to craft the instruction, variables names are for the human, CPUs can only read from addresses, numbers.
This offset will later be and address in memory once the file is loaded.
The assembler, the linker and the loader cooperate, there are various tricks at play, to make sure the final instruction is properly formed in memory and that the offset is transformed into the right address.
In your example their efforts culminate in the value 103h, that is the address of a in memory.
Again, in your example, the offset, if the file is a COM (by the way, don't put variables in the execution flow), was still 103h due to the peculiar structure of the COM files.
But in general, it could have been another number.
BB is MOV r16, imm16 with the register BX. The base form is B8 with the lower 3 bits indicating the register to use, BX is denoted by a value of 3 (011b in binary) and indeed 0B8h + 3 = 0BBh.
After the opcode, again, the WORD immediate 0400 that encodes 4 in little endian.
You now are in the position to realise that the assembly source is not always fully informative, as the assemblers implement some form of syntactic sugar.
The instruction mov ax, a, identical to mov bx, 4 in its syntax and that technically is move the immediate value, constant and known at assembly time, given by the address of a into ax, is instead interpreted as move the content of a, a value present in memory and readable only with a memory access, into ax because a is known to be a variable.
This phenomenon is limited in the x86, being CISC, and more widespread in the RISC world, where the lack of commonly needed instructions is compensated with pseudo-instructions.
Well, first, assembler is x86 Assembly. The assembler is what turns the instructions into machine code.
When you disassemble programs, it probably will use the hex values (like 90 is NOP instruction or B8 to move something to AX).
Square brackets copies the memory address to which the register points to.
The hex on the side is called the address.
Everything is very simple. The command mov ax, cx: [0103] means that the value of 000Ah is loaded into the register ax. This value is taken from the code segment at 0103h. Slightly higher in the pictures you can see this value. cx: 0101 0B900A00. Accordingly, at the address 0101h to be the value 0Bh, 0102h to be the value 90h, 0103h to be the value 0Ah, 0104h to be the value 00h. It turns out that the AL register loads the value from the address 0103h equal to 0Ah. It turns out that the AH register loads the value from the address 0104h equal to 00h and it turns out ax = 000Ah. If instead of the ax command, cx: [0103] there was the ax command, cx: [0101], then ax = 900Bh or the ax command, cx: [0102], then ax = 0A90h.

Random number generator in AVR Studio (no C or any other programming language!)

so I have this question, I have been given a task to do a bombard game with AVR Studio. To be true, I have no clue on how to use AVR and my programming is not so good as well. I got my ships done somehow, but now I need a random number generator. Have been looking throughout Internet for about 2 days now, only found source codes in C, in Java, in absolutely every other language but not the one I need. Could anyone suggest me in what to write for the RAND? for now, my source code looks like this:
;ports
.equ PORTC = $15 ;port C address
.equ DDRC = $14
.equ PORTA = $15 ;port A address
.equ DDRA = $14
;registers
.def leds = r16 ;storing data for leds
.def temp = r18 ;Temporary storage register
.def save = r19 ;Temporary storage register for status registers
.def YL = r20 ;Defining low bite of Y
.def YH = r21 ;Defining high bite of Y
;
.equ SREG = $3F ;Status Register Address
.equ SPH = $3E ;High bite Stack Pointer address
.equ SPL = $3D ;Low bite Stack Pointer address
.equ RAMEND = $25F ;Stack Address
;Random number generator
ldi r16, $80
ldi r17, $C0
;Set stack pointer to registers
ldi temp,high(RAMEND)
out SPH,temp
ldi temp,low(RAMEND)
out SPL,temp
;Initialise output ports
ldi temp, $ff
out DDRC, temp
clear: clc
; clr leds
out PORTC, leds
rjmp SHIP2_prep
SHIP1_prep: ldi leds, $80
rjmp SHIPS
SHIP2_prep: ldi leds, $80
out PORTC, leds
ldi leds, $C0
rjmp SHIPS
SHIP3_prep: ldi leds, $80
out PORTC, leds
ldi leds, $C0
out PORTC, leds
ldi leds, $E0
rjmp SHIPS
;Rotate ships right
SHIPS: out PORTC, leds
; rcall delay
ror leds
brcs clear
rjmp SHIPS
;delay: in save,SREG
; ldi YH,high($FF9C)
; ldi YL,low($FF9C)
loop: sbiw Y,1
brne loop
out SREG, save
ret
The question is more than a year old but I found it while looking for a bog-simple RNG for an AVR assembler project as well. I found it frustrating that StackOverflow had no solution! I've meanwhile found one I like so I'd like to contribute it.
DISCLAIMERS:
This is a very simple 16-bit RNG. It's extremely insecure cryptographically insofar as if the algorithm and current number (even in parts) are known, the next number can be reliably predicted. Also, the sequence of numbers it produces will repeat after 65535 numbers. It can be used for no-risk "toy" projects like that of the original question or mine.
The sequence of numbers produced depends completely on the first, "seed" number. Same seed, same numbers, always. You'll want to find a "really" random source for that seed. I pull a number out of the 16-bit timer when the user presses a button.
If the seed number is 0, the output will be an infinite sequence of 0's. To get a sequence of "useful" pseudo-random numbers you need to start with a number (any number) other than 0.
In summary, if this code breaks, you get to keep both pieces.
All that said, I found it amazing that this could be accomplished in essentially 6 lines of assembler code.
My algorithm is based on the C code shown in the Galois LFSR section of the Wikipedia article on linear feedback shift registers.
Lightly tested for quality.
To ensure I wasn't implementing garbage, I copied the C code, wrapped a bit of test code around it and assured myself that it was indeed producing sequences of length 65535 for at least a handful (5) of test seeds.
I ran my AVR assembler implementation (for AtTiny2313, but it should run on most AVR models) in the simulator in AtmelStudio with the same test seeds and verified that the first 20 numbers in each sequence were the same as in the C program.
Enough waffling! Here's my code:
.INCLUDE "tn2313def.inc"
start:
ldi xl, low(1234)
ldi xh, high(1234)
again: rcall galois
nop ; do something with rn here...
rjmp again
galois: ; subroutine for computing the next prime in X
lsr xh
ror xl
brsh noxor
ldi r17, $B4
eor xh, r17
noxor:
ret
The basic idea is easily extensible to generators with more bits and longer periods simply by increasing the number of registers and using a different suitable "tap polynomial" encoding than $B400.

I need to reverse this PPC Line: clrldi r11, r31, 32

I need to reverse this PPC Line: clrldi r11, r31, 32 I know clrldi it means Clear Left Word Double Immediate. But I dont know how to reverse it so can someone give me advise on reversing it. :)
It's equivalent to generating a mask of zeroes from bit 0-31 and ones from bit 32-63, so the mask is 0x00000000FFFFFFFF. The mask is ANDed with r31 and the result is placed in r11. The mask clears the left side of the register. Check out rldicl and how the extended mnemonic clrldi is interpreted in the PowerPC User ISA Book 1. It will help explain it as well.
If I were to code this in C, it would look like:
r11 = r31 & 0x00000000FFFFFFFFLL;

OS development - converting logical block format to Cylinder-Head-Sector

I am referring BrokenThorn's OS development tutorial, and currently reading the part on developing a complete first stage bootloader that loads the second stage - Bootloaders 4.
In the part of converting Logical Block Address (LBA) to Cylinder-Head-Sector (CHS) format, this is the code that is used -
LBACHS:
xor dx, dx ; prepare dx:ax for operation
div WORD [bpbSectorsPerTrack] ; divide by sectors per track
inc dl ; add 1 (obsolute sector formula)
mov BYTE [absoluteSector], dl
xor dx, dx ; prepare dx:ax for operation
div WORD [bpbHeadsPerCylinder] ; mod by number of heads (Absolue head formula)
mov BYTE [absoluteHead], dl ; everything else was already done from the first formula
mov BYTE [absoluteTrack], al ; not much else to do :)
ret
I am not able to understand the logic behind this conversion. I tried using a few sample values to walk through it and see how it works, but that got me even more confused. Can someone explain how this conversion works and the logic used ?
I am guessing that your LBA value is being stored in AX as you are performing division on some value.
As some pre-information for you, the absoluteSector is the CHS sector number, absoluteHead is the CHS head number, and absoluteTrack is the CHS cylinder number. Cylinders and tracks are the exact same thing, just a different name.
Also, the DIV operation for your code in 16-bit will take whatever is in the DX:AX register combination and divide it by some value. The remainder of the division will be in the DX register while the actual result will be in the AX register.
Next, the *X registers are 16-bit registers, where * is one of ABCD. They are made up of a low and high component, both referred to as *H and *L for high and low, respectively. For example, the DX register has DH for the upper 8 bits and DL for the lower 8 bits.
Finally, as the BYTE and WORD modifiers simply state the size of the data that will be used/transferred.
The first value you must extract is the sector number, which is obtained by diving the LBA value by the number of sectors per track. The DL register will then contain the sector number minus one. This is because counting sectors starts at 1, which is different than most values, which start at zero. To fix this, we add one to the DL register get the correct sector value. This value is stored in memory at absoluteSector.
The next value you must extract is the head number, which is obtained by dividing the result of the last DIV operation by the number of heads per cylinder. The DL register will then contain the head number, which we store at absoluteHead.
Finally, we get the track number. With the last division we already obtained the value, which is in the AL register. We then store this value at absoluteTrack.
Hope this cleared things up a little bit.
-Adrian

Appending 0 before the hexa number

I have been instructed by my teacher to append 0 before the hexa numbers while writing instructions as some compilers search for 0 before the number in an instruction to differentiate it from a label. I am confused if the instruction already starts with a 0, what should be done in such a case?
For Example,
AND BL, 0FH
Is there a need of adding 0 before that hexa number or not? Please help me out. Thanks
EDIT:
Sorry if I had not been clearer enough before. What I meant was that in the above example, a 0 is already present, do I need to convert it to,
AND BL, 00FH
Except for the special cases like 0 or 1, I tend to encode my hex numbers with the full complement of digits just so it's easier to see what the intent is:
mov al, 09h
mov ax, 0123h
and so on.
For cases where the number starts with an alpha character (like deadbeef), I prefix it with an extra 0.
But no, it's not usually (a) necessary to do this if your hex number already begins with a digit.
In any case, I'd be putting most numbers into an equ statement rather than sprinkling magic numbers throughout the code. Would you rather see:
mov ax, 80
or:
mov ax, lines_per_screen
(a) Of course, it depends on your assembler but, from memory, all the ones I've used work this way.
No, there's no need (and including more than one leading 0 is fairly unusual).
Your example is an apt one though -- without the leading 0 to tell it this was a number, the assembler would normally interpret FH as a symbol rather than a number.

Resources