How do we store large decimal/hex value in ARMs? - arm64

I run into a roadblock and not sure where to go from here. I know MOV can only store a maximum of 0-65535 in decimal. However, the value I'm trying to store is 30,402,460.
I was going to use MVN as some source mention that can store bigger number in this format:
MVN X9, #(num), #(num). However 30402460 / 110 = only equals 276,386 which is still above the decimal value of 65535 so I can't use MVN.
My question is; how do we store 30402460 to X9?

MOV is not a real instruction. It's an alias that will be turned into either MOVK, MOVN or ORR as appropriate. But each of those have their own constraints:
MOVZ can load an arbitrary 16 bits, left-shifted by 0, 16, 32 or 48 bits. So you can only use this for values with 48 bits of all zeroes.
MOVN does the same as MOVZ, but inverts the register value. So you can only use this for values with at least 48 bits of all ones.
ORR can construct a really complicated bitmask which, as best as I can tell, can be any sequence of consecutive runs of zeroes, ones, zeroes or ones, zeroes, ones, repeated by any power of two that is a dividend of the register width. So you can load values like 0xaaaaaaaaaaaaaaaa, 0xfffffff00fffffff and 0x18, but not values like 0x0 or 0x5.
The value 30402460 matches none of these constraints. The usual practice for loading such values is to use MOVZ followed by MOVK, the latter of which allows replacing 16 bits of a register without changing the other bits. So in your case:
movz x9, 0x1cf, lsl 16
movk x9, 0xe79c

Related

Is there an opcode that sets a value up to 2147483647 in Game Guardian

I'm creating lua scripts for game guardian(hacking app), i ran into a problem the other day. I found in a 32 bit dump a method like get_ID_Skin that gets the skin's ID. But I can't compose an opcode that would set skin IDs greater than 65535 to the method. An example looks like this: movw r9, #0~65535. In my game, most skin IDs are greater than 65535. Is there an opcode that sets this method to values ​​greater than 65535, preferably up to 2147483647.

Does ALU know about postfix notation?

As we all know, the ALU perform Arithmetic operation, but does the computer understand post-fix notation or not?
Assuming you mean Arithmetic/Logic Unit, no. The ALU does not understand any notation. It only understands instructions. So, for example, the machine code might include an instruction to "add R10 to R11 and store the result in R9," say (disassembled) ADD R9, R10, R11, but the machine code "notation" is understood by the Control Unit, not the ALU.
By the time the ALU receives the information, it is encoded in the form of various control lines being asserted. For instance, in the above example, the CU might assert control lines for "add," "input A is R10," "input B is R11," and "store result in R9." These lines determine how the ALU and the register file behave, and result in the operation desired.
Textual notation, such as 5 + 8 or (+ x 19) or x 19 15 + * or indeed ADD R9, R10, R11, is understood by software, doing processing at a much higher level than the ALU does. It is that software that interprets, say, postfix notation, and issues the instructions that cause the ALU to execute the desired operations.

How can I store the value 2^128-1 in memory (16 bytes)?

According to this link What are the sizes of tword, oword and yword operands? we can store a number using this convention:
16 bytes (128 bit): oword, DO, RESO, DDQ, RESDQ
I tried the following:
section .data
number do 2538
Unfortunately the following error returns:
Integer supplied to a DT, DO or DY instruction
I don't understand why it doesn't work
If your assembler does not support 128 bit integer constants with do then you can achieve the same thing with dq by splitting the constant into two 64 bit halves, e.g.
section .data
number do 0x000102030405060708090a0b0c0d0e0f
could be implemented as
section .data
number dq 0x08090a0b0c0d0e0f,0x0001020304050607
Unless some other code needs it in memory, it's cheaper to generate on the fly a vector with all 128 bits set to 1 = 0xFF... repeating = 2^128-1:
pcmpeqw xmm0, xmm0 ; xmm0 = 0xFF... repeating
;You can store to memory if you want, e.g. to set a bitmap to all-ones.
movups [rdx], xmm0
See also What are the best instruction sequences to generate vector constants on the fly?
For the use-case you described in comments, there's no reason to mess with static data in .data or .rodata, or static storage in .bss. Just make space on the stack and pass pointers to that.
call_something_by_ref:
sub rsp, 24
pcmpeqw xmm0, xmm0 ; xmm0 = 0xFF... repeating
mov rdi, rsp
movaps [rdi], xmm0 ; one byte shorter than movaps [rsp], xmm0
lea rsi, [rdi+8]
call some_function
add rsp, 24
ret
Notice that this code has no immediate constants larger than 8 bits (for data or addresses), and it only touches memory that's already hot in cache (the bottom of the stack). And yes, store-forwarding does work from wide vector stores to integer loads when some_function dereferences RDI and RSI separately.

x86 Assembly: Writing a Program to Test Memory Functionality for Entire 1MB of Memory

Goal:
I need to write a program that tests the write functionality of an entire 1MB of memory on a byte by byte basis for a system using an Intel 80186 microprocessor. In other words, I need to write a 0 to every byte in memory and then check if a 0 was actually written. I need to then repeat the process using a value of 1. Finally, any memory locations that did not successfully have a 0 or 1 written to them during their respective write operation needs to be stored on the stack.
Discussion:
I am an Electrical Engineering student in college (Not Computer Science) and am relatively new to x86 assembly language and MASM611. I am not looking for a complete solution. However, I am going to need some guidance.
Earlier in the semester, I wrote a program that filled a portion of memory with 0's. I believe that this will be a good starting point for my current project.
Source Code For Early Program:
;****************************************************************************
;Program Name: Zeros
;File Name: PROJ01.ASM
;DATE: 09/16/14
;FUNCTION: FILL A MEMORY SEGMENT WITH ZEROS
;HISTORY:
;AUTHOR(S):
;****************************************************************************
NAME ZEROS
MYDATA SEGMENT
MYDATA ENDS
MYSTACK SEGMENT STACK
DB 0FFH DUP(?)
End_Of_Stack LABEL BYTE
MYSTACK ENDS
ASSUME SS:MYSTACK, DS:MYDATA, CS:MYCODE
MYCODE SEGMENT
START: MOV AX, MYSTACK
MOV SS, AX
MOV SP, OFFSET End_Of_Stack
MOV AX, MYDATA
MOV DS, AX
MOV AX, 0FFFFh ;Moves a Hex value of 65535 into AX
MOV BX, 0000h ;Moves a Hex value of 0 into BX
CALL Zero_fill ;Calls procedure Zero_fill
MOV AX, 4C00H ;Performs a clean exit
INT 21H
Zero_fill PROC NEAR ;Declares procedure Zero_fill with near directive
MOV DX, 0000h ;Moves 0H into DX
MOV CX, 0000h ;Moves 0H into CX. This will act as a counter.
Start_Repeat: INC CX ;Increments CX by 1
MOV [BX], DX ;Moves the contents of DX to the memory address of BX
INC BX ;Increments BX by 1
CMP CX, 10000h ;Compares the value of CX with 10000H. If equal, Z-flag set to one.
JNE Start_Repeat ;Jumps to Start_Repeat if CX does not equal 10000H.
RET ;Removes 16-bit value from stack and puts it in IP
Zero_fill ENDP ;Ends procedure Zero_fill
MYCODE ENDS
END START
Requirements:
1. Employ explicit segment structure.
2. Use the ES:DI register pair to address the test memory area.
3. Non destructive access: Before testing each memory location, I need to store the original contents of the byte. Which needs to be restored after testing is complete.
4. I need to store the addresses of any memory locations that fail the test on the stack.
5. I need to determine the highest RAM location.
Plan:
1. In a loop: Write 0000H to memory location, Check value at that mem location, PUSH values of ES and DI to the stack if check fails.
2. In a loop: Write FFFFH to memory location, Check value at that mem location, PUSH values of ES and DI to the stack if check fails.
Source Code Implementing Preliminary Plan:
;****************************************************************************
;Program Name: Memory Test
;File Name: M_TEST.ASM
;DATE: 10/7/14
;FUNCTION: Test operational status of each byte of memory between a starting
; location and an ending location
;HISTORY: Template code from Assembly Project 1
;AUTHOR(S):
;****************************************************************************
NAME M_TEST
MYDATA SEGMENT
MYDATA ENDS
MYSTACK SEGMENT STACK
DB 0FFH DUP(?)
End_Of_Stack LABEL BYTE
MYSTACK ENDS
ESTACK SEGMENT COMMON
ESTACK ENDS
ASSUME SS:MYSTACK, DS:MYDATA, CS:MYCODE, ES:ESTACK
MYCODE SEGMENT
START: MOV AX, MYSTACK
MOV SS, AX
MOV SP, OFFSET End_Of_Stack
MOV AX, MYDATA
MOV DS, AX
MOV AX, FFFFH ;Moves a Hex value of 65535 into AX
MOV BX, 0000H ;Moves a Hex value of 0 into BX
CALL M_TEST ;Calls procedure M_TEST
MOV AX, 4C00H ;Performs a clean exit
INT 21H
M_TEST PROC NEAR ;Declares procedure M_TEST with near directive
MOV DX, 0000H ;Fill DX with 0's
MOV AX, FFFFH ;Fill AX with 1's
MOV CX, 0000H ;Moves 0H into CX. This will act as a counter.
Start_Repeat: MOV [BX], DX ;Moves the contents of DX to the memory address of BX
CMP [BX], 0000H ;Compare value at memory location [BX] with 0H. If equal, Z-flag set to one.
JNE SAVE ;IF Z-Flag NOT EQUAL TO 0, Jump TO SAVE
MOV [BX], AX ;Moves the contents of AX to the memory address of BX
CMP [BX], FFFFH ;Compare value at memory location [BX] with FFFFH. If equal, Z-flag set to one.
JNE SAVE ;IF Z-Flag NOT EQUAL TO 0, Jump TO SAVE
INC CX ;Increments CX by 1
INC BX ;Increments BX by 1
CMP CX, 10000H ;Compares the value of CX with 10000H. If equal, Z-flag set to one.
JNE Start_Repeat ;Jumps to Start_Repeat if CX does not equal 10000H.
SAVE: PUSH ES
PUSH DI
RET ;Removes 16-bit value from stack and puts it in IP
M_TEST ENDP ;Ends procedure Zero_fill
MYCODE ENDS
END START
My commenting might not be accurate.
Questions:
1. How do I use ES:DI to address the test memory area?
2. What is the best way to hold on to the initial memory value so that I can replace it when I'm done testing a specific memory location? I believe registers AX - DX are already in use.
Also, if I have updated code and questions, should I post it on this same thread, or should I create a new post with a link to this one?
Any other advice would be greatly appreciated.
Thanks in advance.
How do I use ES:DI to address the test memory area?
E.g. mov al, es:[di]
What is the best way to hold on to the initial memory value so that I can replace it when I'm done testing a specific memory location? I believe registers AX - DX are already in use.
Right. You could use al to store the original value and have 0 and 1 pre-loaded in bl and cl and then do something like this (off the top of my head):
mov al, es:[di] // load/save original value
mov es:[di], bl // store zero
cmp bl, es:[di] // check that it sticks
jne #pushbad // jump if it didn't
mov es:[di], cl // same for 'one'
cmp cl, es:[di]
jne #pushbad
mov es:[di], al // restore original value
jmp #nextAddr
#pushbad:
mov es:[di], al // restore original value (may be redundant as the mem is bad)
push es
push di
#nextAddr:
...
Some words about for to test also the memory location that our own routine is claimed. We can copy and run our routine into the framebuffer of the display device.
..
Note: If we want to store or compare a memory location with an immediate value, then we have to specify how many bytes we want to access. (But in opposite of it with using a register as a source, or a target, the assembler already knows the size of it, so we do not need to specify.)
Accessing one byte of one address (with an immediate value):
CMP BYTE[BX], 0 ; with NASM (Netwide Assembler)
MOV BYTE[BX], 0
CMP BYTE PTR[BX], 0 ; with MASM (Microsoft Macro Assembler)
MOV BYTE PTR[BX], 0
Accessing two bytes of two adresses together
(executing faster, if the target address is even aligned):
CMP WORD[BX], 0 ; with NASM
MOV WORD[BX], 0
CMP WORD PTR[BX], 0 ; with MASM
MOV WORD PTR[BX], 0
If you start with the assumption that any location in RAM might be faulty; then this means you can't use RAM to store your code or your data. This includes temporary usage - for example, you can't temporarily store your code in RAM and then copy it to display memory, because you risk copying corrupted code from RAM to display memory.
With this in mind; the only case where this makes sense is code in ROM testing the RAM - e.g. during the firmware's POST (Power On Self Test). Furthermore; this means that you can't use the stack at all - not for keeping track of faulty areas, or even for calling functions/routines.
Note that you might assume that you can test a small area (e.g. find the first 1 KiB that isn't faulty) and then use that RAM for storing results, etc. This would be a false assumption.
For RAM faults there are many causes. The first set of causes is "open connection" and "shorted connection" on either the address bus or the data bus. For a simple example, if address line 12 happens to be open circuit, the end result will be that the first 4 KiB always has identical contents to the second 4 KiB of RAM. You can test the first 4 KiB of RAM as much as you like and decide it's "good", but then when you test the second 4 KiB of RAM you trash the contents of the first 4 KiB of RAM.
There is a "smart sequence" of tests. Specifically, test the address lines from highest to lowest (e.g. write different values to 0x000000 and 0x800000 and check that they're both correct; then do the same for 0x000000 and 0x400000, then 0x000000 and 0x200000, and so on until you get to addresses 0x000000 and 0x000001). However, the way RAM chips are connected to the CPU is not necessarily as simple as a direct mapping. For example, maybe the highest bit of the address selects which bank of RAM; and in that case you'd have to test both 0x000000 and 0x400000 and also 0x800000 and 0xC00000 to test both banks.
Once you're sure the address lines work; then you can do similar for data lines and the RAM itself. The most common test is called a "walking ones" test; where you store 0x01, then 0x02, and so on (up to 0x80). This detects things like "sticky bits" (e.g. where a bit's state happens to be "stuck" to its neighbour's state). If you only write (e.g.) 0x00 and test it then write 0xFF and test it, then you will miss most RAM faults.
Also; be very careful with "open connection". On some machines bus capacitance can play tricks on you, where you write a value and the bus capacitance "stores" the previous value, so that when you read it back it looks like it's correct even when there's no connection. To avoid this risk, you need to write a different value in between - e.g. write 0x55 to the address you're testing, then write 0xAA somewhere else, then read the original value back (and hope you get 0x55 because the RAM works, and not 0xAA). With this in mind (for performance) you may consider doing "walking ones" in one area of RAM while also doing "walking zeros" in the next area of RAM; so that you're always alternating between reading a value from one area and reading the inverted value from the other.
Finally, some RAM problems depend on noise, temperature, etc. In these cases you can do extremely thorough RAM tests, say that it's all perfect, then suffer from RAM corruption 2 minutes afterwards. This is why (e.g.) the typical advice is to run something like "memtest" for 8 hours or so if you really want to test RAM properly.

How do I print a long integer that I have in a register?

I have defined a long integer as follows:
memTotal: .long 0
Then, I am adding to it with something like this:
addl 12(%di), %ecx
Where I then move %ecx to memTotal. My question is, how would I go about calculating the size in MB of the memTotal. I tried something along the lines of:
shrl $20, %eax
But how would I then print that as in int for MB?
Am I on the right track? Any help is appreciated.
I assume you know how to print a single ASCII character. So now you need an algorithm to extract the digits from an integer a - I will provide one that I think is easy to understand and easy to expand (it's not necessarily the best).
calculate b := a%10. b is the last digit of your number
set a := a/10 (integer division)
repeat from beginning to get second-to-last digit, etc. Stop when a == 0.
Once you have the value of a digit, you can add a fixed constant to get its ASCII value, which you can use to print the corresponding character.
The above enables you to print a number. Unfortunately, at this point you can only print it backwards. In order to fix that, allocate a string in which you can put the digits from right to left. Start by allocating a string that will be large enough to hold all long ints, then come up with a modification of the above algorithm that will keep track of how many digits there are, and allocate a string accordingly.
(And yes, shrl $20, %eax sounds sensible for turning bytes into what is usually called MiBs. Conventions vary, but I think the usual one is 1 MB = 10^6 bytes, and 1 MiB = 2^20 bytes.)

Resources