Assembly: Define empty 2D array 32bit (NASM + Intel syntax) - linux

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.

Related

How to read declaring an array size?

I've got an array declaration which results in 144 slots.
I don't understand how I've got to this number. Also, what means all those commas between numbers?
Dim arr4(1, 5, 5, 0 To 1) As Long
Debug.Print ArraySize(arr4)
The , denotes a new dimension. So arr4 has 4 dimensions.
When using 0 to 1 it is saying that the fourth dimension has two, 0 and 1
When using just one number 5 then the starting point is assumed 0 unless changed in the settings, so there are 6 in that dimension: 0,1,2,3,4,5
The reason there are 144 is because 2*6*6*2=144
Think of it this way.
1st dimension is rows with two row (0,1)
2nd dimension is columns with 6 columns (0,1,2,3,4,5)
3rd dimension create 6 sheets of the above configuration (0,1,2,3,4,5)
4th dimension create 2 workbooks with each having 6 sheets with 12 cells (0,1)
Thus there is 144 cells in which to put data.

Use of Vector Cross in Ms Excel - 3D arrays and Redim

I'm facing an issue with the use of Redim in VBA of MS Excel in a 3D array. How can I append a new array with different dimension than the first one to the first array and then another one and then ...; and then be able to read a specific group of data from this newly created matrix (array) with different number of columns in each row, for example, the 2nd group of data. Here is an example to clarify the matter.
Arr1 is in 3x3
Arr2 is in 5x5
Arr3 is in 7x7
Arr4 is in 9x9
Arr5 is in 11x11 dimensions.
Now if I append them together the resulting matrix should be in this format - for example:
1 2 3
4 5 6
7 8 9
1 2 3 4 5
6 7 8 9 1
2 3 4 5 6
7 8 9 1 2
3 4 5 6 7
...
...
1 2 3 ... 11
1 2 3 ... 11
(another 8 rows)
1 2 3 ... 11
(total of 11 rows)
Next I want to be able to read a group of data (sub-matrix) from the resulting matrix, for example the 2nd group of data, which is in 5x5.
If I use Redim in between each loop, while appending those new group of arrays and so to adjust the dimensions of the first matrix and continuing to do so, the last dimension will be in 11x11, which does not give me the needed dimension; in this case 5x5.
I was wondering, if there is any recommendation you could kindly provide. Thank you.

excel incrementation by consecutive numbers

I have a form, thanks to user JamTay317, That lists data depending on folder number (bold number in form). I need to copy it for all 1500 folders (about 400 pages)
Form is divided on 4 labels on a page for easier printing
form overview
Form get it's folder number (nr teczki) from list with all folders from another sheet called "lista teczek":
list of folders
For first 4 folder numbers I use formula:
A2='lista teczek'!A1
J2='lista teczek'!A2
A21='lista teczek'!A3
J21='lista teczek'!A4
When I copy whole page underneath it increments by 36 (number of rows between)
A38='lista teczek'!A37
J38='lista teczek'!A38
A57='lista teczek'!A39
J38='lista teczek'!A40
Instead of A5, A6, etc.
Is there any way to override excel's incrementation to force it to use consecutive numbers? Or at least formula which will make it easier to follow folders list?
So I would use offset() to get the correct position
=A2=OFFSET('lista teczek'!$A$1;ROW(A1)-INT(ROW(A1)/36)*36+4*INT(ROW(A1)/36)-1;0)
So this will offset from A1 in the list sheet.
Below are row numbers a resultant lookup row numbers
Note the formula I used in the offset has an extra "-1" as this is an OFFSET so to get 1 from 1 we need to offset by 0
1 1
2 2
3 3
4 4
37 5
38 6
39 7
40 8
73 9
74 10
75 11
76 12
109 13
110 14
111 15
112 16
145 17
146 18
147 19
----LOGIC--- (edit)
So the idea is that you work out the occurrence you are on. Int(row()/36) gives us this. For example
int(1/36)=0
Int(363/36)=10
First part gives us the offset from the start of the occurrence
3-int(3/36)*36=3
378-Int(363/36)*36=3
Second part give the total of the previous occurrence
4*int(3/36)=0
4*Int(363/36)*36=40
So you need to change the 36 to the gap between the occurrences and the 4 to the length of occurrences Not sure if that helps to explain

Z80 Software Delay

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.

Empty integer array variables are outputting as zeroes, some as empties. So confused

I'm writing an Ada program to solve sudoku puzzles. Right now I'm just trying to get the array to fill and output correctly. I take in a text document like so:
4 5 7 89
2 5 6
79 542
35 6489
3 8
6847 91
238 59
79 3 2 1
1 6 7 3
where spaces are empty squares.
The array declaration:
Sudoku_Array : array (1..9, 1..9) of Integer;
Here's the code for assigning values to the array. Is_Char_Number checks if the character is 0-9, and ConverttoNum converts Char to an integer. The array should just have a null value where spaces are.
Open(File, In_File, Argument(1));
while not End_Of_File(File) loop
for R in 1..9 loop
for C in 1..9 loop
Get(File, Char);
if Is_Char_Number(Char) then
Sudoku_Array(R,C) := ConverttoNum(Char);
end if;
end loop;
end loop;
end loop;
So, if I input the above unfinished sudoku puzzle, I get this out (Put with a width of 2):
4 0 5 0 732630 8 9-1620489328
326304196088 2 0 56846 6 0 0
-161330220832630 7 91163006750 0 5 4 2
32767-1613303064 3 532630 6 4 8 9
1 1 0 3 1 8-161330306432630 0
0 6 8 4 7-1613314008 9 1 1
0 2 3 8-161330220832630 5 9-1623044096
32630 7 94198472 31264732688 2-1615461819 1
1 0 6 6-162053872032630 732630 3
I'm assuming the crazy numbers are null array instances, but some of them are coming out as zeros, as if they're being set as the integer 0.
So, is there a way to properly set an integer array value to null?
And, is there a way to better display the results on the screen? Show a space rather than an insane number.
Thanks
EDIT: Thanks guys, I may have been coming about this the wrong way. Instead of trying to set empty spaces as a null array value, I think I can set it as zero. Because there's no zeroes in a sudoku, They will all have to be changed anyways. Thanks guys! Much appreciated.
Two easy ways : pick one.
1) Initialise the array :
Sudoku_Array : array (1..9, 1..9) of Integer := (others => (others => 0));
This may look odd, but (others => 0) sets every element in a 1-D array to 0, and the other others => clause does this for every row.
2) add a default action in an else clause.
if Is_Char_Number(Char) then
Sudoku_Array(R,C) := ConverttoNum(Char);
else
Sudoku_Array(R,C) := 0;
end if;
I think the initialisation is neater here, but both ways have their uses.
I have no idea how Ada works, but you seem to check only if there is a char with
if Is_Char_Number(Char) then
Sudoku_Array(R,C) := ConverttoNum(Char);
end if;
So if it is a char convert it and put it in the array, and if not? Then you insert a zero that will do what you want I suppose

Resources