68K Assembly Math Formula - 68000

I need to write some Lines in 68k Assembly Language with the math formula:
x^2-5x+6
I want to do it with ADD and SUB commands and MOVE yet somehow I cant define the variable x it says its an undefined Symbol and I cant actually realize where my problem is.
ORG $1000
START: ; first instruction of program
MOVE X*X, D0
MOVE (-5X),D2
MOVE 6,D3
ADD D0, D3
SUB D2, D1
SIMHALT
Errors:
LINE 10 Invalid Syntax
LINE 11 Invalid Syntax

Something like this, assuming basic 68000 (and not 68020 or better).
You may have to fix matters like whether X is a word or long word and deal with matters such as sign extension as its a long time since I did 68k assembler. X is defined as a word constant at the end.
ORG $1000
START: ; first instruction of program
CLR.L D7 ; Clear D0 - alternatively MOVEQ #0,D0
MOVE.W X,D7 ; Read X
; Output initial value...
LEA S1,A1
MOVE.W #255,D1
MOVE.L D7,D1
MOVEQ #17,D0
TRAP #15
LEA SNUL,A1
MOVEQ #13,D0
TRAP #15
MOVE.L D7,D6 ; copy of X
ASL.L #2,D6 ; Multiply by 4
ADD.L D7,D6 ; 4X plus another X = 5X
MULU.W D7,D7 ; X^2
SUB.L D6,D7 ; Subtract 5X from X^2
ADDQ.L #6,D7 ; plus 6
; Output answer...
LEA S2,A1
MOVE.L D7,D1
MOVEQ #17,D0
TRAP #15
SIMHALT ; halt simulator
* Put variables and constants here
S1: DC.B 'Initial :',0
S2: DC.B 'Answer :',0
SNUL: DC.B 0
X: DC.W 1234 ; Initial (fixed) value of X
END START ; last line of source

Declaring variables in assembly doesn't work like it would in C or other similar languages. Let's say you're trying to write the following C function:
int myFunction(int x)
{
return (x**2) + (-5x) + 6;
}
So what you would do is, you would choose a register, say D0, and let that be your input variable. It can also be where the output goes.
myFunction:
MOVE.L D0,D1
MULS D0,D1 ;D1 = x squared
MOVE.L D0,D2
ADD.L D0,D0
ADD.L D0,D0
ADD.L D2,D0 ;D0 = 5X
SUB.L D0,D1 ;D1 = (X^2) - 5X
ADD.L #6,D1 ;D1 = (X^2) - 5X + 6
MOVE.L D1,D0 ;return in D0
RTS
Now, if you wanted to use this function, you would first load the desired value of x into register D0 and then call the function:
MOVE.L #5,D0 ;as an example, calculate the function where x = 5.
JSR myFunction
;the program will resume here after the calculation is done,
;and the result will be in D0.

Related

Trying to understand how jump instruction calculate the address when different Program counter present

Currently I am understanding a RISC-V(ISA) instruction set architecture with three extensions I, M, and C extension. Almost I have understood all the instructions of I, M, and C extension but I haven't found yet that how jumps and branches instructions work when 2 different counter presents and how they calculate the address of the next instruction and the immediate value of the label which we are giving.
Note: In C-extension the Program counter increment with +2, because C means compressed and it contains 16-bit instructions. While in I and M extension the Program counter increment with +4 because I and M contain 32-bit instructions.
I have two examples that I want to understand how jumps and branches calculate the address of the next instructions and immediate value of the label that we are given. Can anyone please provide me or explain the formula of calculating the next address of instruction when jumps or branches occur. I am providing two examples of RISC-V assembly. Kindly please help me. Thanks in advance.
Example 1:
0x0 addi x5,x0,12 #x5 = x0 + 12
0x4 c.addi x6,0 #x6 = x6 + 0
l1:
0x6 c.addi x8,6 #x8 = x8 + 6
0x8 c.jal end # ?
0xA c.li x7,2 #x7 = x7 + 2
end:
0xC c.mv x6,x8 #x6 = x8
0xE bne x5,x6,l1 # ?
0x12 c.add x7,x6 # x7 = x7 + x6
0x14 add x8,x5,x7 # x8 = x5 + x7
0x18 c.jal end # ?
Example 2:
0x0 addi x5,x0,12 #x5 = x0 + 12
0x4 c.addi x6,1 #x6 = x6 + 1
l1:
0x6 c.li x7,1 #x7 = x7 + 1
0x8 beq x6,x7,end # ?
0xC c.add x7,x6 #x7 = x7 + x6
end:
0xE add x8,x5,x7 #x8 = x5 + x7
0x12 c.jal l1 # ?
0x14 sub x9,x8,x6 #x9 = x8 + x6
bne and beq are 32-bit instructions that allow for a 13-bit immediate byte offset, which only requires 12 bits to store since the low bit is always zero and thus not stored (all instructions are multiples of 2 bytes).
The 13-bit immediate is used in a pc-relative addressing mode, so when the conditional branch is taken, the hardware computes:
pc' := pc + signExtend(immediate12 ## 0)
where pc' is the next pc, and ## represents bitwise concatenation.  When the branch is not taken it computes the usual pc' := pc + 4 which is sequential flow.
Sign extension is done to interpret the immediate as signed, and, this means that the immediate can be negative or positive, to jump backwards or forwards, respectively.
The 12 bits of the 13-bit branch target immediate are stored distributed among several fields throughout the instruction.  These fields are selected for good overlap with other immediates, and to allow the register fields to remain in the same place relative to other instruction formats.
The c.jal instruction encodes a 12-bit immediate, within a 16-bit instruction; The immediate is encoded in 11-bits (again because the low bit is always zero, so no need to represent it in the instruction).  The hardware takes the 11-bit encoded immediate, adds an extra 0 to the end to make it 12 bits, and then sign extends to full width (we could also say it first sign extends to full width, then multiplies by 2 — same result).  The operation is pc' := pc + signExtend(imm11 ## 0) where ## is concatenation.
Once we know how the processor computes the branch target pc, pc', we simply reverse computation when assembling instructions.  Subtract the difference between the target label (to) and the current pc (from), then divide by 2 and truncate to fit the field width.
If truncation changes the numeric value, then the immediate is too large for the field of the instruction and thus cannot be encoded.
Inline the encoded immediate field's value:
0x0 addi x5,x0,12 #x5 = x0 + 12
0x4 c.addi x6,0 #x6 = x6 + 0
l1:
0x6 c.addi x8,6 #x8 = x8 + 6
0x8 c.jal end # ? **(to-from)/2=(0xC-0x8)/2=2**
0xA c.li x7,2 #x7 = x7 + 2
end:
0xC c.mv x6,x8 #x6 = x8
0xE bne x5,x6,l1 # ? **(0x6-0xE)/2=-4**
0x12 c.add x7,x6 # x7 = x7 + x6
0x14 add x8,x5,x7 # x8 = x5 + x7
0x18 c.jal end # ? **(0xC-0x18)/2=-6**
0x0 addi x5,x0,12 #x5 = x0 + 12
0x4 c.addi x6,1 #x6 = x6 + 1
l1:
0x6 c.li x7,1 #x7 = x7 + 1
0x8 beq x6,x7,end # ? **(0xE-0x8)/2=3**
0xC c.add x7,x6 #x7 = x7 + x6
end:
0xE add x8,x5,x7 #x8 = x5 + x7
0x12 c.jal l1 # ? **(0x6-0x12)/2=-6**
0x14 sub x9,x8,x6 #x9 = x8 + x6
Sign extension is used to make a short signed field into a full width value.
An 11 bit encoded immediate, as in c.jal, using -6 and +6 as examples, would look like this in binary:
# Example using -6
* The bit under the * is the MSB
|
11111111010 # -6 in 11 bits
11111111111111111111111111111010 # -6 in 32 bits
********************* Copied from the MSB in 11 bits
# Example using +6
* The bit under the * is the MSB
|
00000000110 # 6 in 11 bits
00000000000000000000000000000110 # 6 in 32 bits
********************* Copied from the MSB in 11 bits
The Most Significant Bit is the top bit and if 1 means the number is negative.  In order to preserve the value when widening (e.g. from 11 to 32 bits), propagate the MSB in the shorter field across all the bits of extra width.
Not sure if this is the best way to do it
<p id="x"></p> // replace **{{c}}** blank element hence it will impact anything
After the successful ajax call
success: function(data){ // data will hold whatever is returned from the url
$("#x").html(data['c']); // This will populate the p element with your value
alert("Hello");
},
You can also hide the ment

Compare user-inputted string/character to another string/character

So I'm a bit of a beginner to ARM Assembly (assembly in general, too). Right now I'm writing a program and one of the biggest parts of it is that the user will need to type in a letter, and then I will compare that letter to some other pre-inputted letter to see if the user typed the same thing.
For instance, in my code I have
.balign 4 /* Forces the next data declaration to be on a 4 byte segment */
dime: .asciz "D\n"
at the top of the file and
addr_dime : .word dime
at the bottom of the file.
Also, based on what I've been reading online I put
.balign 4
inputChoice: .asciz "%d"
at the top of the file, and put
inputVal : .word 0
at the bottom of the file.
Near the middle of the file (just trust me that there is something wrong with this standalone code, and the rest of the file doesn't matter in this context) I have this block of code:
ldr r3, addr_dime
ldr r2, addr_inputChoice
cmp r2, r3 /*See if the user entered D*/
addeq r5, r5, #10 /*add 10 to the total if so*/
Which I THINK should load "D" into r3, load whatever String or character the user inputted into r2, and then add 10 to r5 if they are the same.
For some reason this doesn't work, and the r5, r5, #10 code only works if addne comes before it.
addr_dime : .word dime is poitlessly over-complicated. The address is already a link-time constant. Storing the address in memory (at another location which has its own address) doesn't help you at all, it just adds another layer of indirection. (Which is actually the source of your problem.)
Anyway, cmp doesn't dereference its register operands, so you're comparing pointers. If you single-step with a debugger, you'll see that the values in registers are pointers.
To load the single byte at dime, zero-extended into r3, do
ldrb r3, dime
Using ldr to do a 32-bit load would also get the \n byte, and a 32-bit comparison would have to match that too for eq to be true.
But this can only work if dime is close enough for a PC-relative addressing mode to fit; like most RISC machines, ARM can't use arbitrary absolute addresses because the instruction-width is fixed.
For the constant, the easiest way to avoid that is not to store it in memory in the first place. Use .equ dime, 'D' to define a numeric constant, then you can use
cmp r2, dime # compare with immediate operand
Or ldr r3, =dime to ask the assembler to get the constant into a register for you. You can do this with addresses, so you could do
ldr r2, =inputVal # r2 = &inputVal
ldrb r2, [r2] # load first byte of inputVal
This is the generic way to handle loading from static data that might be too far away for a PC-relative addressing mode.
You could avoid that by using a stack address (sub sp, #16 / mov r5, sp or something). Then you already have the address in a register.
This is exactly what a C compiler does:
char dime[4] = "D\n";
char input[4] = "xyz";
int foo(int start) {
if (dime[0] == input[0])
start += 10;
return start;
}
From ARM32 gcc6.3 on the Godbolt compiler explorer:
foo:
ldr r3, .L4 # load a pointer to the data section at dime / input
ldrb r2, [r3]
ldrb r3, [r3, #4]
cmp r2, r3
addeq r0, r0, #10
bx lr
.L4:
# gcc greated this "literal pool" next to the code
# holding a pointer it can use to access the data section,
# wherever the linker ends up putting it.
.word .LANCHOR0
.section .data
.p2align 2
### These are in a different section, near each other.
### On Godbolt, click the .text button to see full assembler directives.
.LANCHOR0: # actually defined with a .set directive, but same difference.
dime:
.ascii "D\012\000"
input:
.ascii "xyz\000"
Try changing the C to compare with a literal character instead of a global the compiler can't optimize into a constant, and see what you get.

for-loop(downto,Reversed) vs for-loop(increase mode) vs while-loop in Delphi

I have a micro-optimization issue. I have 3 methods for processing typed-Pointer(array) . Which one is better?
1
for I:=0 to ArrCount-1 do
begin // I:Var is unused in below-block
Inc(P) ; // P is typed-Pointer
// do somethings
end;
2
for I:=ArrCount-1 downto 0 do
begin // I:Var is unused in below-block
Inc(P) ; // P is typed-Pointer
// do somethings
end;
3
While ArrCount>0 do
begin
Inc(P) ; // P is typed-Pointer
// do somethings
Dec(ArrCount);
end;
The answer that I will give to this question is rather more mundane than perhaps you are expecting. The fastest of these variants is the one that, wait for it, is timed to run most quickly.
It's entirely plausible that on different architectures you'll find that different variants win.
It's also conceivable that different variants will win depending on what is in the body of the loop.
It's also quite possible that the body of the loop takes sufficient time that the loop itself is negligible in comparison.
In short, it depends. Since only you know what happens inside the body, only you can answer the specific question.
As an aside, if the loop body does not refer to the loop variable, then the compiler re-writes the ascending loop as if it were a descending loop. So there may in fact be only two variants here. Indeed, that might mean that all three variants lead to identical compiled code!
Some advice:
Never optimise without profiling.
Never optimise code that is not a bottleneck.
Now, if you want me to take a guess, I predict that for any loop body that is more than a trivial nop, you'll find it hard to find any measurable difference between these variants.
I also see that you are using a pointer to walk across an array. You might find that if this code is a bottleneck, and if the loop body just handles this array iteration, that using arr[] indexing is more effective that pointer arithmetic. But again, it depends on many things and you have to profile, and look at the code the compiler produces.
Funny, but looking at disassembly window the speed is depending on weather is the loop variable used inside loop.
1) Not using - code is almost identical:
Project17.dpr.12: for i := 0 to 3 do
0040914D B804000000 mov eax,$00000004
Project17.dpr.13: Inc(j);
00409152 43 inc ebx
Project17.dpr.12: for i := 0 to 3 do
00409153 48 dec eax
00409154 75FC jnz $00409152
Project17.dpr.15: for i := 3 downto 0 do
00409156 B8FCFFFFFF mov eax,$fffffffc
Project17.dpr.16: Inc(j);
0040915B 43 inc ebx
Project17.dpr.15: for i := 3 downto 0 do
0040915C 40 inc eax
0040915D 75FC jnz $0040915b
2) Used - first variant faster a bit because xor faster then mov:
Project17.dpr.12: for i := 0 to 3 do
0040914D 33C0 xor eax,eax
Project17.dpr.13: Inc(j, i);
0040914F 03D8 add ebx,eax
00409151 40 inc eax
Project17.dpr.12: for i := 0 to 3 do
00409152 83F804 cmp eax,$04
00409155 75F8 jnz $0040914f
Project17.dpr.15: for i := 3 downto 0 do
00409157 B803000000 mov eax,$00000003
Project17.dpr.16: Inc(j, i);
0040915C 03D8 add ebx,eax
0040915E 48 dec eax
Project17.dpr.15: for i := 3 downto 0 do
0040915F 83F8FF cmp eax,-$01
00409162 75F8 jnz $0040915c
You can check third variant yourself.
PS: I am using D2007 for this test.

Trouble With Reading In A String With A Subroutine In LC3

So I believe that the way I store the string works. I am just having some issues passing the String out of the subroutine. I heard that in order to pass something out of a subroutine you need to store it in R1 but I can't get it to store into my WORD array
.orig x3000
AND R1,R1,0
LEA R0,PROMPT
PUTS
JSR GETS
ST R1,WORD
LEA R0,WORD
PUTS
halt
; ---------Data Area-------------
WORD .blkw 20
PROMPT .stringz "Enter String: "
; -------------------------------
GETS LEA R1,MEMORYBLOCK ; saves the address of the storage memory block
loop GETC ; input character -> r0
PUTC ; r0 -> console
; always points at the next available block
LD R2,EMPTY ; check for
ADD R2,R2,R0 ; end of line
BRz finish
LD R2,COUNTDOWN
ADD R2,R2,#-1
BRz finish
ST R2,COUNTDOWN
STR R0,R1,#0 ; r0 -> ( memory address stored in r1 + 0 )
ADD R1,R1,#1 ; increments the memory pointer so that it
BR loop
finish LEA R1,MEMORYBLOCK
RET
; ----Subroutine Data Area-------
EMPTY .fill xfff6
COUNTDOWN .fill #10
MEMORYBLOCK .BLKW 20
; -------------------------------
.end
The biggest problem here is the concept of "returning a string". What you're actually doing at the end of GETS is returning the memory address at which the string starts. When you then store this into WORD in the calling function, you are storing the memory address of the first byte of the string that was input (i.e. the memory address of MEMORYBLOCK) into the first byte of WORD. You aren't copying the entire string from MEMORYBLOCK into WORD.
The easiest "fix" for what you're trying to do would be to change
LEA R0,WORD
to
LD R0,WORD
and then for good measure:
WORD .blkw 20
to
WORD .fill 0
as now you're just using it to store a single value (i.e. the memory address of MEMORYBLOCK).
However, at this point you haven't made a copy of the string. If you want to do this, then you will need to make a loop whereby you walk through MEMORYBLOCK and copy each byte to WORD instead.
The final, cheaper, way to do this is to just use MEMORYBLOCK directly from the calling function. It's not really any less valid in a program of this size, unless there's project requirements that ask otherwise.

Using relative values in array sorting ( asm )

I need to sort through an array and sort each individual row in array to be in ascending order. I doesn't seem to going so well (surprise!) as I keep getting hit with two errors:
a2101: cannot add two relocatable labels
and
a2026: constant expected
Here's my sort, it makes sense to me, but I think I'm still trying to implement high-lvl language techniqes into assembly. Is there a way to get around not being able to use relative values? (the array is 7 rows by 9 columns, btw).
mov cx, 7; cx = number of rows
outer: ; outer loop walk through the rows
push cx
mov cx, 9
mov row, cx ;rows
middle: ; middle-loop walk through the columns
push cx
sub cx, 1 ;cx = cx-1
mov column, cx ;columns
inner: ;inner loop - compare and exchange column values
cmp mArray[row*9 + column], mArray[row*9 + column+1]
xchg mArray[row*9 + column+1], mArray[row*9 + column]
; compare and exchange values from mArray table
inc column
loop inner
pop cx
loop middle ;end middle loop
pop cx
loop outer ; end outer loop
ret
Thanks for any help.
The following lines are problematic:
cmp mArray[row*9 + column], mArray[row*9 + column+1]
xchg mArray[row*9 + column+1], mArray[row*9 + column]
Unlike HLL, assembly does NOT allow for arbitrary expressions in place of constants or variables. That's why HLL's were invented in the first place. Calculate the offset in the registers before using:
mov ax, row
mov bx, ax
shr bx, 3 ; bx = row*8 now
add bx, ax ; bx = row*9 now
add bx, column ; bx = row*8+column now
mov dx, [bx] ;first comparand
inc bx
cmd dx, [bx] ; that's your compare!
Also, you don't use any branching; the cmp instruction is utterly pointless; you waste its result, and xcng is not executed conditionally. Read up on conditional jump commands (jz/jnz etc.).
Also, I seriously hope this is an exercise, not a real project. If it's for real, please reconsider using assembly. For something as trivial as this, assembly is a wrong, wrong choice. Espec. considering how bad you are at it.

Resources