can anyone help me on this exercice on 68000 assembler please?
create a program that multiply two long words v1 and v3 unsigned. the product is number on 64 bits. the values v1 qnd v2 are respectively on the data registers D1 and D2 ?
thanks for your answers and sorry for my bad english
As long as you multiply unsigned 32-bit quantities, you can use the following way:
Theory: if your 32-bit quantities are A and B, split them like this:
A=Ah*0x10000+Al, B=Bh*0x10000+Bl, where each of Ah,Al,Bh,Bl is from 0 to 0xFFFF.
Then, obviously,
A * B = Ah * Bh<<32 + Al * Bh<<16 + Ah * Bl<<16 + Al * Bl
Each of these 4 multiplies is 16bit*16bit->32bit, thus perfectly fitting 68000 mulu.w command.
So the code:
;unsigned d0.l * d1.l -> d2.l:d3.l (d2.l holds high part)
move.w d0,d3
mulu.w d1,d3 ;d3.l is Al*Bl now
swap d0
swap d1
move.w d0,d2
mulu.w d1,d2 ;d2.l is Ah*Bh now
swap d0
move.w d0,d4
mulu.w d1,d4 ;d4 is Al*Bh
swap d4
moveq #0,d5
move.w d4,d5
clr.w d4 ; d5:d4 is 0x0000:Nh:Nl:0x0000, where N is Al*Bh
add.l d4,d3
addx.l d5,d2 ;add Al*Bh*0x10000 to the partial result in d2:d3
swap d0
swap d1
move.w d0,d4
mulu.w d1,d4 ;d4 is Ah*Bl
swap d4
moveq #0,d5
move.w d4,d5
clr.w d4 ; d5:d4 is 0x0000:Nh:Nl:0x0000, where N is Ah*Bl
add.l d4,d3
addx.l d5,d2 ;add Ah*Bl*0x10000 to the partial result
;d2:d3 is now the result
Of course, this code has many possibilities for optimization.
You have the problem that the MUL is only 16-bit, which means that if you have a 64-bit result, you need to do it in a sequence of 4 16-bit multiples and additions. You then return the result in two registers, as each register is 32-bits.
Assume you want A x B, and that A is AH and AL, with B as BH and BL
You get a series of partial products:
1: BL x AL
2: BL x AH x 2^16
3: BH x 2^16 x AL
4: BH x 2^16 x AH x 2^16
Each of the 4 partial products accumulate in their own section of the 64-bit word, and to make matters more interesting, you need to consider the carries.
What I will present is different from what you need as far as registers, but if you can understand it, you can change it for your exercise. Assume that A6 is the stack, and we’ll return the result in D0 for the high 32-bit word, and D1 for the low 32-bit word. Here’s a snippet of code from my library
umul32: link a6, #0
movem.l d2-d4, -(sp)
move.l (multiB,a6), d4 ;B into d4
move.l (multiA,a6), d3 ;A into d3
moveq #0,d2
moveq #0,d1
moveq #0,d0
mshift1: lsr.l #1,d4 ; look for 1 in multiplier
bcc.s mshift2 ; branch on 0
add.l d3,d1 ; add shifted A to product
addx.l d2,d0 ; add carry if found
mshift2: lsl.l #1,d3 ; shift for next iteration
roxl.l #1,d2
tst.l d4 ; check for 1s
bne.s mshift1
movem.l (sp)+,d2-d4
ulnk a6
move.l (sp),(8,sp) ;clean the 8 entries off the stack
addq.l 8, sp
rts
This is code generated by Amiga Aztec C compiler for multiplying two 32 bits integers :
D0/D1 : input
D0 : output
move.w d1,d2
mulu d0,d2
move.l d1,d3
swap d3
mulu d0,d3
swap d3
clr.w d3
add.l d3,d2
swap d0
mulu d1,d0
swap d0
clr.w d0
add.l d2,d0
rts
Related
I need help with making some IF/OR/AND statements.
I have a cell (C8) that can be one of fourteen different variables. Depending on the value for C8 either cells F8, D8, or E8 will be used in three possible equations.
C D E F G H
7
8
9
C8 can equal any of the following values
0.5,0.55,0.6,0.7,0.75,1,1.0625,1.125,1.1875,1.25,1.325,1.375,1.4375,1.5
Equations needed:
IF C8 equals any values from 0.6 - 1.5 will then need to solve for (100-(F8-108)*5))+(G8+1))
IF C8 equals 0.5 will then need to solve for (100-((D8-56)*5)+(G8*1))
IF C8 equals 0.55 will then need to solve for (100-((E8-102)*5)+(G8*1)
I currently have this equation C8 if values are 0.6 1.5
=IF(AND(SUMPRODUCT(--ISNUMBER(SEARCH({0.6,0.65,0.7,0.75,1,1.0625,1.125,1.1875,1.25,1.325,1.375,1.4375,1.5},C8)))>0),100-(((F8-108)*5)+(G8*1)),"")
I think I need an IF/OR statement for two additional Situation
C8 equals 0.5 to solve for 100-(((D8-56)*5)+(G8*1))
C8 equals 0.55 to solve for 100-(((E8-102)*5)+(G8*1))
The following is the they type of IF/OR formulas I have tried.
=IF(OR(SUMPRODUCT(--ISNUMBER(SEARCH({0.6,0.65,0.7,0.75,1,1.0625,1.125,1.1875,1.25,1.325,1.375,1.4375,1.5},C8)))>0), 100-(((F8-108)*5)+(G8*1)), OR(ISNUMBER(SEARCH({0.5,C8)))>0)100-(((D8-56)*5)+(G8*1)), OR(ISNUMBER(SEARCH({0.55,C8))>0)100-(((E8-102*5)+(G8*1))"")
=IF(OR(SUMPRODUCT(--ISNUMBER(SEARCH({0.6,0.65,0.7,0.75,1,1.0625,1.125,1.1875,1.25,1.325,1.375,1.4375,1.5},C8)))>0), 100-(((F8-108)*5)+(G8*1)), (ISNUMBER(SEARCH({0.5,C8)))>0)100-(((D8-56)*5)+(G8*1)), (ISNUMBER(SEARCH({0.55,C8))>0)100-(((E8-102*5)+(G8*1))"")
Do you need to search for the values? If the cell can only equal one of the values you shared you can just build your statement around that assumption.
If that assumption is false, this will not work. [Equation3] will be called when C8 equals anything BUT .50 & .55 so C8 has to have limitations for this to work.
IF(C8 = .50, [Equation1], IF(C8 = .55, [Equation2], [Equation3]))
Where
[Equation1] = (100-((D8-56)*5)+(G8*1))
[Equation2] = (100-((E8-102)*5)+(G8*1)
[Equation3] = (100-(F8-108)*5))+(G8+1))
How can we define empty 2D array 251x256 for 32 bit code in assembly?
I have an old example in 16 bit code for assembly:
DataIn byte 251 dup (256 dup (?))
Now I would like to declare the same thing but that will work for 32 bit architectures for NASM.
You can declare a one dimensional array and access it as two dimensional by calculating the offset of each row and adding the column. In your case, your array is 251 rows and 256 columns, so you can multiply 256 by the desired row and add the column, example :
section .data
array resb 251*256 ;251 ROWS X 256 COLUMNS.
_start:
mov eax,256 ;ROW SIZE (256 COLUMNS PER ROW).
mov ebx,35 ;DESIRED ROW (35).
mul ebx ;EAX * EBX = 8960.
mov esi,array ;POINT TO ARRAY.
add esi,eax ;POINT TO DESIRED ROW (35).
add esi,20 ;POINT TO DESIRED COLUMN (20).
This is for type byte, for bigger types it will be necessary to multiply by the size (by 2, by 4, etc).
From all the help in the comments I think I figured it out.
1. There is no such things as 2D arrays in assembly
2 4 6
3 6 9
7 8 9
Are located in memory like this: 2 4 6 3 6 9 7 8 9
2. So the only way to create "2D" array is to improvise.
3. We can keep 2 counters that will keep track of our improvised 2D array.
4. So for every 3 numbers we will increase the counter for rows and we will "move" to the next improvised row.
I am trying to create a software delay. Here is a sample program of what I am doing:
Address Data Opcode Comment
1800 06 LD, B Load register B with fix value
1801 “ “ Fixed value
1802 05 DEC, B Decrement value in register B
1803 C2 JP cc Jump to 1802 if value is not 0
1804 02 - Address XX
1805 18 - Address XX
My question is how can I calculate the required fixed value to load into register B so that the process of decrementing the value until 0 takes 2 seconds?
In my manual the time given to run the instructions is based on a 4MHz CPU but the Z80 CPU I am using has a speed of 1.8MHz. Any idea how I can calculate this? Thanks. P.S here is the decrement (DEC) and jump (JP cc) instructions from the manual:
Instruction M Cycles T states 4 MHz E.t
DEC r 1 4 1.00
JP cc 3 10 (4,3,3) 2.50
If by 1.8MHz you mean exactly 1,800,000 Hz, then to get a 2 second delay you'd need to delay for 3,600,000 T-states. Your current delay loop takes 14 T-states per iteration, which means that your initial value for B would have to be 3600000/14 == 257143, which obviously won't fit in one byte.
The greatest number of iterations that you could specify with an 8-bit register is 256, and to reach 3,600,000 T-states with 256 iterations, each iteration would have to take 14,062 T-states. That's one big loop body.
If we use a 16-bit counter things start getting a bit more manageable. At 65,536 iterations we only need 55 T-states per iteration to reach a total of 3,600,000 T-states. Below is an example of what that could look like:
; Clobbers A, B and C
ld bc,#0
1$:
bit #0,a ; 8
bit #0,a ; 8
bit #0,a ; 8
and a,#255 ; 7
dec bc ; 6
ld a,c ; 4
or a,b ; 4
jp nz,1$ ; 10, total = 55 states/iteration
; 65536 iterations * 55 states = 3604480 states = 2.00248 seconds
I'm a bit of an optimization freak, so here is my go using the syntax with which I am most familiar (from the TASM assembler and similar):
Instruction opcode timing
ld bc,$EE9D ;01EE9D 10cc
ex (sp),hl ;E3 19*(256C+B)
ex (sp),hl ;E3 19*(256C+B)
ex (sp),hl ;E3 19*(256C+B)
ex (sp),hl ;E3 19*(256C+B)
djnz $-4 ;10FA 13cc*(256C+B) - 5*C
dec c ;0D 4*C
jr nz,$-7 ;20F7 12*C-5
This code is 12 bytes and 3600002 clock cycles.
EDIT: It seems like part of my answer is gone! To answer your question better, your Z80 can process 1800000 clock cycles in one second, so you need twice that (3600000). If you add up the timings given in my code, you get:
=10+(256C+B)(19*4+13)-5C+4C+12C-5
=5+(256C+B)89+11C
=5+22795C+89B
So the code timing is largely dependent on C. 3600000/22795 is about 157, so we initialize C with 157 (0x9D). Plugging this back in, we get B to be roughly 237.9775, so we round that up to 238 (0xEE). Plugging these in gets our final timing of 3600002cc or roughly 2.000001 seconds. This assumes that the processor is running at exactly 1.8MHz which is very unlikely.
As well, if you can use interrupts, figure out roughly how many times it fires per second and use a loop like halt \ djnz $-1 . This saves a lot more in terms of power consumption.
Im looking for a way to convert the file as below called INPUT to OUTPUT. The file INPUT consists of columns consisting the unique ID, ID and the value. I would like to convert the ID to separated IDs based on the value as distinction. I tried some basic commands but could not manage to make it work for the main input file which is 20,000 rows and has 15,000 IDs.
Does anyone has some nice ideas/suggestions how to handle this problem?
INPUT OUTPUT
unique ID VALUE unique ID VALUE
A1 GENEA 10 -> A1 GENEAp1 10
A2 GENEA 5 -> A2 GENEAp2 5
A3 GENEA 2 -> A3 GENEAp3 2
A4 GENEB 4 -> A4 GENEBp4 4
A5 GENEB 5 -> A5 GENEBp3 5
A6 GENEB 8 -> A6 GENEBp2 8
A7 GENEB 70 -> A7 GENEBp1 70
A8 GENEC 5 -> A8 GENECp1 5
A9 GENED 50 -> A9 GENEDp2 50
A10 GENED 10 -> A10 GENEDp3 10
Preferably the numbering of p based on the value. With p1 with the highest value, p2 second highest etc.
Here's a crazy one-liner that does it:
head -1 file; tail -n+2 file| nl| sort -nrk4| awk '{ ++m[$3]; print($1" "$2" "$3"p"m[$3]" "$4); }'| sort -n| cut -d' ' -f2-4| column -to' ';
Output:
unique ID VALUE
A1 GENEAp1 10
A2 GENEAp2 5
A3 GENEAp3 2
A4 GENEBp4 4
A5 GENEBp3 5
A6 GENEBp2 8
A7 GENEBp1 70
A8 GENECp1 5
A9 GENEDp1 50
A10 GENEDp2 10
It involves sorting the file by the VALUE column, and then processing it sequentially in awk, counting occurrences of each distinct ID in an associative array, so you can build up the p# count.
Additional notes:
I printed the header line (head -1) separately from the data lines (tail -n+2) so the main processing pipeline would only apply to the data lines.
I added a call to nl before the initial sort to capture the original line order in a new leading numbering column, and then sorted by that column afterward (and then cut out that numbering column) to return to the original order.
I added column -to' ' at the end to align the data lines, don't know if you want/need that. If you want to align the header line with the data lines, you can surround the head statement and main pipeline with a braced block and move the column -to' ' filter outside the braced block to align the whole thing.
This is a simple SystemVerilog question that I am having a surprisingly difficult time finding the answer for.
In this kind of bit array initialization syntax, is the b[0] part assigned to a's most significant bit, or the least significant bit?
bit a[7:0];
bit b[7:0] = 8'hff;
bit c[7:0] = 8'h00;
a = {b[0], c[6:0]};
So does a[0] == 1 or a[7] == 1?
The reason you've found it hard to find an answer is because the result is dependent on how you've declared things.
You've declared a to be [7:0]. Therefore the bits in a are arranged like this:
a7 a6 a5 a4 a3 a2 a1 a0
You then assign {b[0], c[6:0} to a:
a7 a6 a5 a4 a3 a2 a1 a0 = b0 c6 c5 c4 c3 c2 c1 c0
1 0 0 0 0 0 0 0 = 1 0 0 0 0 0 0 0
A[7] == 1
If you'd declared a to be [0:7] the result would have been:
a0 a1 a2 a3 a4 a5 a6 a7 = b0 c6 c5 c4 c3 c2 c1 c0
1 0 0 0 0 0 0 0 = 1 0 0 0 0 0 0 0
A[0] == 1
b[0] is assigned to the most significant bit, a[7]; i.e. a[7] == 1.
However, I'm not sure it's typo or your intention to use unpacked declaration. bit a[7:0] is an unpacked array, it does not mean continuous storage and it can not be directly assigned packed or integral value.
Following is adopted from SystemVerilog for Design, P.114, 5.3.1 Unpacked arrays
Unpacked array stores each element independently, but grouped under a common array name.
P.122, 5.3.5 Assigning values to arrays
SystemVerilog extends Verilog with two additional ways to assign values to unpacked arrays:
- The entire array can be assigned a list of values
- A slice of the array can be assigned a list of values.
The list of values is specified between '{ } braces, the same as with initializing unpacked arrays.
For packed array, bit [7:0] a, we do have correct answer from Paul.