Understanding condition code flag setting in assembly - c

If I have the following table:
Case 1: x: 42 y: -15 (y-x) = -57
Case 2: x: -17 y: -17 (y-x) = 0
Case 3: x: 0x7ffffffd y: -67 (y-x) = 2147483584
Case 4: x: 67 y: -0x7fffffffd (y-x) = 2147483584
What would the condition code flags set (zero or one, per flag) for ZF SF OF and CF
when considering the instruction: cmp1 %eax %ecx if %eax contains x and %ecx contains y?
I understand that cmp1 ...,... is executed by: cmp1 SRC2,SRC1
which means: "sets condition codes of SRC1 – SRC2"
I understand that the flags represent:
OF = overflow (?)
ZF = zero flag i.e. zero...
CF = carry out from msb
SF - sign flag i.e. negative
For my four cases in the table, I believe the flags would be:
1) ZF = 0 SF = 1 CF = 0 OF = ?
2) ZF = 1 SF = 0 CF = 0 OF = ?
3) ZF = 0 SF = 0 CF = 1 OF = ?
4) ZF = 0 SF = 0 CF = 1 OF = ?
Am I correct? Please explain what CF and OF are and how to determine if either will be set TRUE, and correct any of my flawed understanding. Thank you.

Carry overflow occurs when an arithmetic operation generates a carry that cannot fit into the register. So if you had 8-bit registers, and wanted to add 10000000 and 10000000 (unsigned):
10000000
10000000
--------
100000000
This 1 is the carry from most significant bit, and thus sets CF = 1.
You might also want to check this other answer.

Related

I am Using PSoC 5. I want to know about how to convert 8-Byte hexadecimal into decimal after reading from EEPROM

EEPROM Data:
0000: 88 77 66 55 44 33 22 11 00 00 00 00 00 00 00 00
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
I am saving the result after reading 0th row of EEPROM in array
Ex - Uint8 EEPROM_res[8];
EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};
I want to convert HexaDecimal(0x8877665544332211) into decimal (9833440827789222417) and save the decimal value into integer data type for further comparison. What is the easiest way of conversion of 8-Byte Hexadecimal?
Can you share the algorithm? – Shivangi Kishore
Converting base 10 (seconds) to base 60 (hours:minutes:seconds)
4321 seconds (in base 10) to base 60.
60^0 = 1
60^1 = 60
60^2 = 3600
60^3 = 216000
(just like 10^0 = 1, 10^1 = 10 and 10^2 = 100 ... base 10, 2^0 = 1, 2^1 = 2, 2^2 = 4 and so on base 2)
So 4321 is less than 216000 but greater than 3600 so we can shortcut and start there
4321 / 3600 = 1 remainder 721
721 / 60 = 12 remainder 1
So 4321 base 10 converted to base 60 (using base 10 to do the math) is 01:12:01
base 2 to base 10 using a base 2 computer is no different.
10 factors into 2 and 5, 2 factors into 2, so you cannot do base 8 (octal) to base 2 shortcuts nor can you do base 16 (hex) to base 2 shortcuts. Have to do it the long way.
EDIT
Another approach that may be more useful to you is to work from the other end. Same math just done using remainders instead of results. Makes for an easier algorithm to program.
4321 / 60 = 72 remainder 1
72 / 60 = 1 remainder 12
1 / 60 = 0 remainder 1
conversion to base 60: 01:12:01
1234 / 10 = 123 remainder 4
123 / 10 = 12 remainder 3
12 / 10 = 1 remainder 2
1 / 10 = 0 remainder 1
conversion to base 10: 1234
Long division in binary is the same but simpler than in a base greater than 2 because the divisor on each step through the denominator can either go into the test value 0 times or 1 time. binary...base 2...
Also if you think through long division (254 / 5 or 0xFE / 0x5)
------------
101 ) 11111110
this is the first test cases that is non-zero
001
------------
101 ) 11111110
101
and you keep going
001
------------
101 ) 11111110
101
---
10
and
0011
------------
101 ) 11111110
101
---
101
101
---
0
and
00110010
------------
101 ) 11111110
101
---
101
101
---
0111
101
---
100
and so 0xFE / 5 = 0x32 remainder 4, but the key here is that I could
do that in hardware with a hardware divide instruction if I have say an 8 bit divide instruction and want to divide an infinitely long number.
If my next (let's say) four digits were 1010:
0001110
101 1001010
101
===
1000
101
===
111
101
===
100
0xFEA / 5 = 0x32E remainder 4
So now I have divided a 12 bit number using an 8 bit divider instruction and I can do this all day long until I run out of ram. 8 bits, 88 bits, 888 bits, 8888 bits, a million bits divided by a small number like 5 or 10.
Or if you keep working on this you find that compilers often use multiply we also know from grade school (since all of this problem is solved with grade school math).
x / 10 = x * (1/10)
More likely to find a hardware multiply than a divide and the multiply is often fewer clocks, etc.
unsigned int fun ( unsigned int x )
{
return(x/10);
}
00000000 <fun>:
0: e59f3008 ldr r3, [pc, #8] ; 10 <fun+0x10>
4: e0802093 umull r2, r0, r3, r0
8: e1a001a0 lsr r0, r0, #3
c: e12fff1e bx lr
10: cccccccd stclgt 12, cr12, [r12], {205} ; 0xcd
0000000000000000 <fun>:
0: 89 f8 mov %edi,%eax
2: ba cd cc cc cc mov $0xcccccccd,%edx
7: f7 e2 mul %edx
9: 89 d0 mov %edx,%eax
b: c1 e8 03 shr $0x3,%eax
e: c3 retq
and other instruction sets, the compiler multiplies by 1/5 then compensates (base 10, 10 factors to 2 and 5, base 2, 2 factors to 2 a common factor).
But if your hardware doesn't have a multiply or divide the compiler should still handle the basic C language variable types, long, int, short, char. And you can cascade those all day long.
unsigned int fun ( unsigned int x )
{
unsigned int ra;
unsigned int rb;
unsigned int rc;
ra=((x>>4)&0xFF)/5;
rb=((x>>4)&0xFF)%5;
rb=(rb<<4)|(x&0xF);
rc=rb/5;
ra=(ra<<4)|rc;
return(ra);
}
test it on the development machine
#include <stdio.h>
extern unsigned int fun ( unsigned int );
int main ( void )
{
printf("%X\n",fun(0xFEA));
return(0);
}
and the output is 0x32E.
And that really completes it everything you need to know (well you already knew from grade school) to do the conversion with the tools you have available.
If instead you are looking for some big math library for some compiler for some target, having us google things for you is not a Stack Overflow question and should be closed as seeking external or third party libraries.
Now as pointed out
save the decimal value into integer data type for further comparison
makes no sense whatsoever, if you want to take some number and then save it for further comparison on a computer, that function looks like this
void fun ( void )
{
}
It is already in that form you want it to be a integer that means some variable (larger than C supports so that is yet another problem with the wording of the question) so that means binary not decimal, so it is already in a future comparable integer form.
If you want to represent that number visually (as in a human viewable printout) in some base then you need to convert that into something that can be viewed be it base 2 (binary), base 8 (octal), base 16 (hex), base 10 (decimal) and so on.
The bits 11111111 in the computer if I want to see those in binary then
"11111111" in octal "377" in hex "FF" in decimal "255" all of which require an algorithm to convert. Octal and hex of course being the simplest, don't need to use a division routine to convert to octal, base 8, factors are 222 base 2 factors are 2 so 2^3 vs 2^1
11111111 / 8 = 11111111 >> 3 = 11111 r 111
11111 / 8 = 11111 >> 3 = 11 r 111
11 / 8 = 11 >> 3 = 0 r 11
377
Base 10 though you have to go the long way and actually do the division and find the remainder until the result of the division in the loop is 0.
10 has factors 2 and 5, 2 has factors 2 you can't shift your way through it. Base 100, 10*10, and base 10 you can shift your way through (just like base 2 to base 4) but base 10 from base 2, can't.
11111111 / 10 = 11001 r 101
11001 / 10 = 10 r 101
10 / 10 = 0 r 10
255
Which of course is why we greatly prefer to view stuff on the computer in hex rather than decimal.
Once in decimal though
"for further comparison"
once you get it to base 10 then the only reasonable comparison you can do with other base 10 numbers is a string compare or an array compare, from the above example the two more common ways you would store that conversion is 0x32, 0x35, 0x35, 0x00 or 0x02, 0x05, 0x05 with some length knowledge.
You can't do greater than less than without a whole lot of work. Equal vs not equal you could do in base 10 bit it is not in integer form.
So your question doesn't make any sense.
Also assume this is a multi part typo:
EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};
which is the same as
EEPROM_res = {0x58,0x4D,0x42,0x37,0x2C,0x21,0x16,0x0B};
Neither of which are
EEPROM_res = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};
Which is what your first 8 bytes of eeprom dump showed in hexadecimal as you mentioned and is somewhat obvious.
Nor are they
EEPROM_res[19] = {0x39,0x38,0x33,0x33....and so on
or
EEPROM_res[19] = {0x09,0x08,0x03,0x03....and so on
the decimal value you computed somehow: 9833440827789222417

~ Unary Operator and Bitwise Tests Give Negative Results

I was studying bitwise operators and they make sense until the unary ~one's complement is used with them. Can anyone explain to me how this works?
For example, these make sense however the rest of the computations aside from these do not:
1&~0 = 1 (~0 is 1 -> 1&1 = 1)
~0^~0 = 0 (~0 is 1 -> 1^1 = 0)
~1^0 = 1 (~1 is 0 -> 0^1 = 1)
~0&1 = 1 (~0 is 1 -> 1&1 = 1)
~0^~1 = 1 (~0 is 1, ~1 is 0 -> 1^0 = 1)
~1^~1 = 0 (~1 is 0 -> 0^0)
The rest of the results produced are negative(or a very large number if unsigned) or contradict the logic I am aware of. For example :
0&~1 = 0 (~1 = 0 therefor 0&0 should equal 0 but they equal 1)
~0&~1 = -2
~1|~0 = -1
etc. Anywhere you can point me to learn about this?
They actually do make sense when you expand them out a little more. A few things to be aware of though:
Bitwise AND yields a 1 only when both bits involved are 1. Otherwise, it yields 0. 1 & 1 = 1, 0 & anything = 0.
Bitwise OR yields a 1 when any of the bits in that position are a 1, and 0 only if all bits in that position are 0. 1 | 0 = 1, 1 | 1 = 1, 0 | 0 = 0.
Signed numbers are generally done as two's complement (though a processor does not have to do it that way!). Remember with two's complement, you invert and add 1 to get the magnitude when the highest bit position is a 1.
Assuming a 32-bit integer, you get these results:
0 & ~1 = 0 & 0xFFFFFFFE = 0
~0 & ~1 = 0xFFFFFFFF & 0xFFFFFFFE = 0xFFFFFFFE (0x00000001 + 1) = -2
~1 | ~0 = 0xFFFFFFFE & 0xFFFFFFFF = 0xFFFFFFFF (0x00000000 + 1) = -1
0&~1 = 0 (~1 = 0 therefor 0&0 should equal 0 but they equal 1)
~1 equals -2. If you flip all the bits of a Two's Complement number, you multiply it by -1 and subtract 1 from the result. Regardless of that 0 has 0 for all the bits, so the result of & is going to be 0 anyway.
~0&~1 = -2
~0 has all bits set so ~0&~1 is just ~1. Which is -2.
~1|~0 = -1
~0 has all bits set, so the result of the | is ~0 (= -1) no matter what it is OR'd with.
~1 = 0 - No it's not. It's equal to -2. Let's take a eight bit two complement as example. The decimal number 1 has the representation 0000 0001. So ~1 will have 1111 1110 which is the two complement representation of -2.

How are the individual bits accessed in this code?

So I saw this code which printed out individual bits of any number.I do not understand why the individual bits are accessed and not the entire number itself
#include <stdio.h>
int main()
{
int x=10, b;
for(b=0; x!=0; x>>=1) {
printf("%d:%d\n", b, (x&1));
b++;
}
}
OUTPUT:
0:0
1:1
2:0
3:1
Please help me understand this piece of code.
In your code you are printing the value of X variable in binary. For this, your code, use logical operation as AND operator and right-shift.
In the loop condition, you displace the X variable one bit to the right.
for b = 0 you get x = 1010
for b = 1 you get x = 101
for b = 2 you get x = 10
for b = 3 you get x = 1
Then, in your print, show your loop iterator (b) and your X variable AND 1.
The AND operator get this values:
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1
In your case, you have:
1010 AND (000)1 = 0
101 AND (00)1 = 1
10 AND (0)1 = 0
1 AND 1 = 1
There are two questions in your post: how to access an individual bit ? and how to select that bit ?
Concerning the first question, suppose you want to access the less significant bit (or, to make it simpler, the rightmmost bit), you can use a mask: suppose your data is b0011 for instance, you can mask with b0001 (i.e. 1 in decimal).
0 0 1 1
& 0 0 0 1
---------
0 0 0 1
The & operator is the bitwise and. If you look in your code sample, you have printf("%d:%d\n", b, (x&1)); in which you can see x & 1, i.e. print the rightmost bit of x.
Now comes the second question: how to put each bit in the rightmost position one after each other (said otherwise, how to select the bit to print) ? An easy solution is to shift your data of 1 position to the right each time you want to select the next bit (i.e. the bit to the left of the current one).
In C, you can shift using >>. For instance, if x is b0011, then x >> 1 is b0001 (in this case, you fill the leftmost position with zeros, but in some cases it might be trickier). If you look in you code sample, you have x>>=1 in the for-loop, which assigns x >> 1 in x.
Hence, suppose you take the previous example:
0 0 1 1 = x 0 0 0 1 = x
& 0 0 0 1 & 0 0 0 1
--------- x >> 1 = b0001 -> x ---------
0 0 0 1 0 0 0 1
and so one...
A last bonus point, the loop stopping condition is x != 0, this implies that you don't prints all bits of your data, but only the bits up to the leftmost 1 (included). For instance, in the above example, after printing the two rightmost bits, x becomes 0 and the loop exits.

K&R C programming language exercise 2-9

I don't understand the exercise 2-9, in K&R C programming language,
chapter 2, 2.10:
Exercise 2-9. In a two's complement number system, x &= (x-1) deletes the rightmost 1-bit in x . Explain why. Use this observation to write a faster version of bitcount .
the bitcount function is:
/* bitcount: count 1 bits in x */
int bitcount(unsigned x)
{
int b;
for (b = 0; x != 0; x >>= 1)
if (x & 01)
b++;
return b;
}
The function deletes the rightmost bit after checking if it is bit-1 and then pops in the last bit .
I can't understand why x&(x-1) deletes the right most 1-bit?
For example, suppose x is 1010 and x-1 is 1001 in binary, and x&(x-1) would be 1011, so the rightmost bit would be there and would be one, where am I wrong?
Also, the exercise mentioned two's complement, does it have something to do with this question?
Thanks a lot!!!
First, you need to believe that K&R are correct.
Second, you may have some mis-understanding on the words.
Let me clarify it again for you. The rightmost 1-bit does not mean the right most bit, but the right most bit which is 1 in the binary form.
Let's arbitrary assume that x is xxxxxxx1000(x can be 0 or 1). Then from right to left, the fourth bit is the "rightmost 1-bit". On the basis of this understanding, let's continue on the problem.
Why x &=(x-1) can delete the rightmost 1-bit?
In a two's complement number system, -1 is represented with all 1 bit-pattern.
So x-1 is actually x+(-1), which is xxxxxxx1000+11111111111. Here comes the tricky point.
before the righmost 1-bit, all 0 becomes 1 and the rightmost 1-bit becomes 0 and there is a carry 1 go to left side. And this 1 will continue to proceed to the left most and cause an overflow, meanwhile, all 'x' bit is still a because 'x'+'1'+'1'(carry) causes a 'x' bit.
Then x & (x-1) will delete the rightmost 1-bit.
Hope you can understand it now.
Thanks.
Here is a simple way to explain it. Let's arbitrarily assume that number Y is xxxxxxx1000 (x can be 0 or 1).
xxxxxxx1000 - 1 = xxxxxxx0111
xxxxxxx1000 & xxxxxxx0111 = xxxxxxx0000 (See, the "rightmost 1" is gone.)
So the number of repetitions of Y &= (Y-1) before Y becomes 0 will be the total number of 1's in Y.
Why do x & (x-1) delete the right most order bit? Just try and see:
If the righmost order bit is 1, x has a binary representation of a...b1 and x-1 is a...b0 so the bitwise and will give a...b1 because common bits are left unchanged by the and and 1 & 0 is 0
Else x has a binary representation of a...b10...0; x-1 is a...b01...1 and for same reason as above x & (x-1) will be a...b00...0 again clearing the rightmost order bit.
So instead of scanning all bits to find which one are 0 and which one are 1, you just iterate the operation x = x & (x-1) until x is 0: the number of steps will be the number of 1 bits. It is more efficient than the naive implementation because statistically you will use half number of steps.
Example of code:
int bitcount(unsigned int x) {
int nb = 0;
while (x != 0) {
x &= x-1;
nb++
}
return nb;
}
Ik I'm already very late (≈ 3.5yrs) but your example has mistake.
x = 1010 = 10
x - 1 = 1001 = 9
1010 & 1001 = 1000
So as you can see, it deleted the rightmost bit in 10.
7 = 111
6 = 110
5 = 101
4 = 100
3 = 011
2 = 010
1 = 001
0 = 000
Observe that the position of rightmost 1 in any number, the bit at that same position of that number minus one is 0. Thus ANDing x with x-1 will be reset (i.e. set to 0) the rightmost bit.
7 & 6 = 111 & 110 = 110 = 6
6 & 5 = 110 & 101 = 100 = 4
5 & 4 = 101 & 100 = 100 = 4
4 & 3 = 010 & 011 = 010 = 2
3 & 2 = 011 & 010 = 010 = 2
2 & 1 = 010 & 001 = 000 = 0
1 & 0 = 001 & 000 = 000 = 0

How can I remove a flag in C?

There is a variable that holds some flags and I want to remove one of them. But I don't know how to remove it.
Here is how I set the flag.
my.emask |= ENABLE_SHOOT;
Short Answer
You want to do an Bitwise AND operation on the current value with a Bitwise NOT operation of the flag you want to unset. A Bitwise NOT inverts every bit (i.e. 0 => 1, 1 => 0).
flags = flags & ~MASK; or flags &= ~MASK;.
Long Answer
ENABLE_WALK = 0 // 00000000
ENABLE_RUN = 1 // 00000001
ENABLE_SHOOT = 2 // 00000010
ENABLE_SHOOTRUN = 3 // 00000011
value = ENABLE_RUN // 00000001
value |= ENABLE_SHOOT // 00000011 or same as ENABLE_SHOOTRUN
When you perform a Bitwise AND with Bitwise NOT of the value you want unset.
value = value & ~ENABLE_SHOOT // 00000001
you are actually doing:
0 0 0 0 0 0 1 1 (current value)
& 1 1 1 1 1 1 0 1 (~ENABLE_SHOOT)
---------------
0 0 0 0 0 0 0 1 (result)
my.emask &= ~(ENABLE_SHOOT);
to clear a few flags:
my.emask &= ~(ENABLE_SHOOT|SOME_OTHER|ONE_MORE);
It's important to note that if the variable being manipulated is larger than an int, the value used in the 'and not' expression must be as well. Actually, one can sometimes get away with using smaller types, but there are enough odd cases that it's probably best to use type suffixes to make sure the constants are large enough.

Resources