Comparing signed integer in arm assembly - arm

Loading a global variable and checking to see if it's equal to -1 but my code will not recognize it as equal to -1. It only pass the comparison with local variables.
//setting global variable
.data
.global top_m
top_m: .word -1
//loading global variable into x21
adrp x28, top_m
add x28, x28, :lo12:top_m
ldr x21, [x28]
//checking value of global variable, it does not branch to exit_stackEmpty
cmp x21, -1
b.eq exit_stackEmpty
//but if I compare with a local variable then it does branch
mov x23, -1
cmp x23, -1
b.eq exit_stackEmpty
EDIT:
In gdb it shows this for x21 and x23
x21 0xffffffff 4294967295 //after loading -1 to x21
x23 0xffffffffffffffff -1 //after mov x23, -1

The data that you're loading is from a .word directive, and thus is 32 bits - 0xffffffff. If you then load 64 bits from that address you get 0x00000000ffffffff, which indeed is not a 64-bit -1 however you look at it. Incidentally, that load also runs off the end of the data section, which is a bad idea, but does means you'll happen to get zeros in the MSBs (or a segfault) - if you had more data following top_m, it would be more obvious what's happening.
If you want to load a 32-bit word and sign-extend it to 64 bits, use the "load a 32-bit word and sign-extend it to 64 bits" instruction: LDRSW.

Related

LDMIA instruction results in corrupt register data

I'm attempting to run a compiled program on a ARM Cortex-M3 bare metal. Before the system even reaches the application code, an odd error blows the program counter away and errors out.
Before the instruction, the registers are observed to be:
r0 0x0 0
r1 0x1 1
r2 0x0 0
r3 0x2 2
r4 0x18564 99684
r5 0x18418 99352
r6 0x0 0
r7 0x0 0
r8 0x8311 33553
r9 0x0 0
r10 0x0 0
r11 0x0 0
r12 0xc84404 13124612
sp 0x7ffe0 0x7ffe0
lr 0x80df 32991
pc 0x8380 0x8380
The following instruction is executed nominally:
0x829c <__call_exitprocs+112>: ldmia.w sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
And the registers being read explode. It also sends the program counter way off effectively terminating the program.
...
r3 0x2 2
r4 0xffffffff 4294967295
r5 0xffffffff 4294967295
r6 0xffffffff 4294967295
r7 0xffffffff 4294967295
r8 0xffffffff 4294967295
r9 0xffffffff 4294967295
r10 0xffffffff 4294967295
r11 0x0 0
...
pc 0xfffffffe 0xfffffffe
I've read a similar issue on stack overfflow, but it doesn't seem to be the direct issue that I'm facing here. The ATMEL documentation for this board doesn't specify a limitation on number of internal registers read at once on a quick glance.
Any thoughts on the problem and, if possible, a workaround in gcc to prevent it?
The instruction (and its effect) are absolutely correct. But the sp value before this instruction is absolutely wrong. Your chip has no RAM memory on that address. In fact - it probably has no memory at all at this address. See page 32 of the manual (with the memory map).
http://www.atmel.com/Images/Atmel-6430-32-bit-Cortex-M3-Microcontroller-SAM3U4-SAM3U2-SAM3U1_Datasheet.pdf
Your sp should be somewhere within SRAM, so above 0x20000000. The value you have - 0x7ffe0 is somewhere in the "Boot memory" region. If you want to find the problem, find out why sp has invalid value.

How to find largest number in an array using NASM

i was doing a program in NASM(x86 assembly), in which user is asked to enter three 32 bit hex numbers(8 digit), which are further stored in an array and the program shows the number which is largest of them all. The program works fine, i.e. it shows the largest of the three numbers. But the problem is, that it shows only 16 bit (4 digit number) as output. For example, if i give three numbers as 11111111h,22222222h and 10000000h, the output comes out to be only 2222. This is the code.
section .data
msg db "Enter the number : ",10d,13d
msglen equ $-msg
show db "The greatest number is : ",10d,13d
showlen equ $-show
%macro display 2
mov eax,4
mov ebx,1
mov ecx,%1
mov edx,%2
int 80h
%endmacro
%macro input 2
mov eax,3
mov ebx,0
mov ecx,%1
mov edx,%2
int 80h
%endmacro
section .bss
large resd 12
num resd 3
section .text
global _start
_start:
mov esi,num
mov edi,3
; Now taking input
nxt_num:
display msg,msglen
input esi,12
add esi,12
dec edi
jnz nxt_num
mov esi,num
mov edi,3
add: mov eax,[esi]
jmp check
next: add esi,12
mov ebx,[esi]
CMP ebx,eax
jg add
check: dec edi
jnz next
mov [large],eax
display show,showlen
display large,12
;exit
mov eax,1
mov ebx,0
int 80h
I even tried changing reserved size of array from doubly byte to quad byte. But the result remains the same.
Also, when i execute the same code in NASM x86_64 assembly, only with the registers and the system calls changed (i.e. eax to rax, ebx to rcx, int 80h to syscall, etc) the output comes out to of 32 bits(8 digits). Why so?
I need help. Thank you. :)
In you little program , you're trying to move the Qword into a 32-bit register which can hold just 4bytes (DWord). Based on your response to Gunner I guess you're misunderstanding this concept.
Actually each byte is represented by 8bits.
a word is 2 bytes (16 bits)
a dword is 4 bytes (32 bits) which is the size of a register in a x86 arch.
So whenever you take a byte , its binary equivalent has always an 8bits size.
So the binary equivalent of "FF" in hex is 00001111.
In your program just try to print your number as a string instead of printing it through a register, you can simply do that by using the pointer to the memory address where you number is stored or simply by printing the input using printf.
P.S : the string should be in ASCII , so to display 11111111 it should be in memory as following 3131313131313131 .
The output 2222 is correct for a 32 bit register. Each number is 8 bits, 4 numbers = 8 * 4 = 32, the max a 32 bit register can hold. This is why if you change to 64 bit registers, the full number is printed. You will need to change the displayed number into a string to display the full number.

What does an Unsigned Long in C look like in PIC24 Assembly Language?

I have a variable defined in C on a PIC24
Let's say the name of the variable (in the C file) is The_Number_Of_Bytes
In the PIC24 C code, it is defined like this....
unsigned long The_Number_Of_Bytes=0; // number of bytes in buffer
I'm going to be called when an array of bytes named DATABUF01 will contain The_Number_Of_Bytes bytes (sorry for the implied redundancy) and I will need to make sure that I do that many bytes, exactly, and then stop.
I'm pretty confident that the number will be less than 65535, so why it is an unsigned long is for other discussions. For now, I want to know; which is the high order word and which is the low order word ? (For that matter, is long a 32 bit number in PIC24 C ?)
Could somebody tell me What will be in W2 and W3 in this example ?
Mov.W #_The_Number_Of_Bytes, W1 ;From the dispatcher
Mov.W [W1++], W2 ;My question: Hi Order or Low Order ?
Mov.W [W1], W3 ;My question: Hi Order or Low ?
Mov.W #_DATABUF01, W4 ;The Start
Mov.B [W4++], W5 ;First byte...
: ;Whatever
: ;Whatever
: ;Whatever
Could someone please confirm or correct my thinking about Hi / Low order of the unsigned long int ?
EDIT commenter requested this. May answer the question (comments are mine)
Requested comment, The size appears to be 4 bytes, from this...
45: unsigned long i=0;
0AB6A B80060 mul.uu 0x0000,#0,0x0000 ;make a zero
0AB6C 980710 mov.w 0x0000,[0x001c+2] ;no clue which word
0AB6E 980721 mov.w 0x0002,[0x001c+4] ;aha, if I made it 1 or 2, I'd know
46: unsigned int Fischer;
47:
48: Fischer = sizeof(i);
0AB70 200040 mov.w #0x4,0x0000 ;So it must be 4
0AB72 780F00 mov.w 0x0000,[0x001c] ;okay, it's a 4 byte number
49:
Here's a snippet from MPLAB C Compiler for PIC24 MCU's User's Guide:
5.3 DATA REPRESENTATION
Multibyte quantities are stored in “little endian” format, which means:
The least significant byte is stored at the lowest address
The least significant bit is stored at the lowest-numbered bit position
As an example, the long value of 0x12345678 is stored at address 0x100 as follows:
0x1000x1010x1020x103
0x78 0x56 0x34 0x12
As another example, the long value of 0x12345678 is stored in registers w4 and w5:
w4 w5
0x56780x1234
you can also view the assembly for a program to try to get an idea of how their compiler does it... for instance:
int main(int argc, char** argv)
{
long i = 56;
long j = i;
return 0;
}
becomes... ( xc16-gcc -S main.c )
.file "/Users/grady/MPLABXProjects/testpic24.X/main.c"
.section .text,code
.align 2
.global _main ; export
.type _main,#function
_main:
.set ___PA___,1
lnk #12
mov w0,[w14+8]
mov w1,[w14+10]
mov #56,w4
mov #0,w5
mov.d w4,[w14]
mov.d [w14],w4
mov w4,[w14+4]
mov w5,[w14+6]
clr w4
mov w4,w0
ulnk
return
.set ___PA___,0
.section __c30_signature, info, data
.word 0x0001
.word 0x0000
.word 0x0000
; MCHP configuration words
.set ___PA___,0
.end

x86 TEST instruction not working?

I've been banging my head against the wall figuring this out, and this is making no sense to me...
Why does this program enter an infinite loop?!
I thought you could use test to compare two values for equality, as shown here... why doesn't it work?
int main()
{
__asm
{
mov EAX, 1;
mov EDX, EAX;
test EAX, EDX;
L: jne L;
}
}
Your expectation of what the TEST instruction does is incorrect.
The instruction is used to perform bit tests. You would typically use it to "test" if certain bits are set given a mask. It would be used in conjunction with the JZ (jump if zero) or JNZ (jump if not zero) instructions.
The test involves performing a bitwise-AND on the two operands and sets the appropriate flags (discarding the result). If none of the corresponding bits in the mask are set, then the ZF (zero flag) will be 1 (all bits are zero). If you wanted to test if any were set, you'd use the JNZ instruction. If you wanted to test if none were set, you'd use the JZ instruction.
The JE and JNE are not appropriate for this instruction because they interpret the flags differently.
You are trying to perform an equality check on some variables. You should be using the CMP instruction. You would typically use it to compare values with each other.
The comparison effectively subtracts the operands and only sets the flags (discarding the result). When equal, the difference of the two values is 0 (ZF = 1). When not equal, the difference of the two values is non-zero (ZF = 0). If you wanted to test if they were equal, you'd use the JE (jump if equal) instruction. If you wanted to test if they were not equal, you'd use the JNE (jump if not equal) instruction.
In this case, since you used TEST, the resulting flags would yield ZF = 0 (0x1 & 0x1 = 0x1, non-zero). Since ZF = 0, the JNE instruction would take the branch as you are seeing here.
tl;dr
You need to compare the values using the CMP instruction if you are checking for equality, not TEST them.
int main()
{
__asm
{
mov EAX, 1
mov EDX, EAX
cmp EAX, EDX
L: jne L ; no more infinite loop
}
}
Just reading this (my asm is very rusty) and this
JNE jumps on ZF (Zero Flag) = 0
TEST sets ZF = 0 If bitwise EAX AND EDX results in 1 and 1 if bitwise AND results in 0
If the result of the AND is 0, the ZF is set to 1, otherwise set to
0.
Therefore it jumps as 1 AND 1 results in 0 in ZF.
Seems logical yet counter intuative.
I think #A.Webb is right - it should probably be JNZ if you're using the TEST instruction as you are relying on the behavior of a bitwuse operation to set the zero flag whereas the SUB instruction would set the Zero flag as you need.
This is pretty simple. You obviously need to know what the instructions do, what processor state they read, and write. When in doubt, get a reference manual. The Intel x86 manuals are easy to find online.
Your specific program:
mov EAX, 1;
moves the constant 1 to EAX. No other state changes occur.
mov EDX, EAX;
copies the contexts of EAX into EDX, so it too contains the value 1.
test EAX, EDX;
test computes the bitwise AND of two registers (did you check the reference manuals?), throws the answer away, and sets condition code bits based on the answer. In your case, the upper 31 bits of each register is zero, and'd produces zeros. The least significant bit is one in both registers; and'd produces a 1. The net effect is that the 32 binary value "one" is generated, and thrown away after the condition code bits are set. There is one condition code bit we care about for this program, and that's the "Z"(ero) bit, which is set if the last condition-code setting operation produced a full zero value. This test produced "one", so the Z bit is reset. I'll let you look up the other condition code bits.
L: jne L;
This is a "Jmp on Not Equal", e.g, it jmps if the Z bit is reset. For your program, Z is reset, the jmp occurs. After execution, the processor is at the same insruction, and sees another (the same jmp). The condition code bits aren't changed by a jmp instruction.
So... it goes into an infinite loop.
There are lots of synonyms for various opcodes supported by assemblers. For instance, "JZ" and "JE" are synonyms for the same instruction. Don't let the synonyms confuse.

Hardware Processor Counters Incorrectly Resetting

I wrote a program which reads the APERF/MPERF counters on an Intel chip (page 2 on http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-software-developer-vol-3b-part-2-manual.pdf).
These counters are readable/writable via the readmsr/writemsr instructions, and I'm currently simply reading them at a regular interval via a device driver in Windows 7. The counters are 64 bits, and increment approximately with each processor clock, so you'd expect them to overflow in a very long amount of time, but when I read the counters, their value jumps around as if they are being reset by another program.
Is there any way to track down what program would be resetting the counters? Could something else be causing incorrect values to be read? The relevant assembly and corresponding C functions I'm using are attached below. The 64-bit result from rdmsr is saved into eax:edx, so to make sure I wasn't missing any numbers in the r_x registers, I run the command multiple times to check them all.
C:
long long test1, test2, test3, test4;
test1 = TST1();
test2 = TST2();
test3 = TST3();
test4 = TST4();
status = RtlStringCbPrintfA(buffer, sizeof(buffer), "Value: %llu %llu %llu %llu\n", test1, test2, test3, test4);
Assembly:
;;;;;;;;;;;;;;;;;;;
PUBLIC TST1
TST1 proc
mov ecx, 231 ; 0xE7
rdmsr
ret ; returns rax
TST1 endp
;;;;;;;;;;;;;;;;;;;
PUBLIC TST2
TST2 proc
mov ecx, 231 ; 0xE7
rdmsr
mov rax, rbx
ret ; returns rax
TST2 endp
;;;;;;;;;;;;;;;;;;;
PUBLIC TST3
TST3 proc
mov ecx, 231 ; 0xE7
rdmsr
mov rax, rcx
ret ; returns rax
TST3 endp
;;;;;;;;;;;;;;;;;;;
PUBLIC TST4
TST4 proc
mov ecx, 231 ; 0xE7
rdmsr
mov rax, rdx
ret ; returns rax
TST4 endp
The result that prints out is something like below, but the only register which ever changes is the rax register, and it doesn't increase monotonically (can jump around):
Value: 312664 37 231 0
Value: 252576 37 231 0
Value: 1051857 37 231 0
I was not able to figure out what was resetting my counters, but I was able to determine the frequency. The Intel docs state that when one counter overflows, the other counter also will. So even though the counters are constantly resetting, the ratio of aperf and mperf still does represent the processor's frequency.
It seems that Windows 7 and Windows 8 read and reset the writeable APERF/MPERF counters on AMD processors. So, you want to access the read-only APERF/MPERF counters at registers 0xc00000E7/E8.
But there is a new issue. On some of the latest AMD processors (Family 0x16 processors), those registers are not always supported. To determine if those registers are supported, you have to read the EffFreqRO bit in CPUID Fn8000_0007_EDX. As stated before, all this applies only to AMD processors.

Resources