Branch on neg, but not on > 127 because MS bit is set both cases. - Page 1
Forum section: electronics / general

author: Circlotron
author_rank: Super Contributor
timestamp: December 24, 2014, 03:26:39 am
content: LDA with valueSUB "other value" (may be <=> than ASTA safe placeBMI fix possible negative result situation if "other value" > AorBCS fix possible negative result situation if "other value" > AThe trouble is, sometimes the result of the subtraction is > +127 so the MS bit is set so this then looks like a negative number instead of a large positive number if a BMI is tried. At least I think this is the case.What should I do to branch on a negative value but ignore a positive value > 127?

author: westfw
author_rank: Super Contributor
timestamp: December 24, 2014, 06:56:56 am
content: Which CPU? Guessing a 6502?Many CPU architectures combine "minus" with "Carry" and/or "Overflow" to achieve both signed and unsigned comparisons.For example, AVR has "BRSH" (Branch is Same or Higher, unsigned, checks carry) and "BRGE" (Branch if Greater or Equal. Checks Minus and Overflow.) MSP430 had "JHS" (C==1) and "JGE" (N==V) Between this and some 6502 tutorials, it looks like you may want to be looking at the carry flag rather than the Minus flag, when you're dealing with unsigned values.

author: Circlotron
author_rank: Super Contributor
timestamp: December 24, 2014, 07:03:08 am
content: Using a 'HC908.

author: westfw
author_rank: Super Contributor
timestamp: December 24, 2014, 07:59:40 am
content: HC908 also has BHS and BGE as well as BMI...I usually think of BMI as a sort of bit-test instruction rather than being useful for magnitude comparison (possible exception: comparing with zero...)

author: miguelvp
author_rank: Super Contributor
timestamp: December 24, 2014, 08:41:28 am
content: CMP will set the carry flag if the Other value is bigger than the value, but subtract (SUB) does the same as compare so if the result is bigger (carry set) then just adjust the value, so jump with BCC over the adjustment.Not sure about the adjustment, it's late but I think 0 minus the result will do, there might be some faster way to do it.So:LDA with valueSUB "other value"BCC noadjustNot sure about the adjustment, wine and lateEdit this might do the trick:NEGAnoadjust:STA safe placeEdit again: treat the result as unsigned.

author: mikerj
author_rank: Super Contributor
timestamp: December 24, 2014, 09:10:31 am
content: Quote from: Circlotron on December 24, 2014, 03:26:39 amIt sounds like your subtrahend (memory value) and minuend (accumulator value) are both unsigned values since this is only way a valid difference of >127 is possible. Is this correct?If you simply want to detect an underflow condition (i.e. subtrahend>minuend) then the carry bit should be tested.

author: magetoo
author_rank: Frequent Contributor
timestamp: December 25, 2014, 07:22:51 am
content: Quote from: Circlotron on December 24, 2014, 03:26:39 amWhat are the ranges of your inputs?Assuming you have eight bit registers and two's complement arithmetic, then positive values larger than 127 are the same thing as negative values. You have 128 negative values, one zero value, and 127 positive values. That's 256 in total, and that's all there is. Positive values larger than 127 don't exist, andcan'tcoexist with negative values in a strictly 8-bit world.There may be things you can do that involves the carry/borrow flag (in which case you effectively get 9-bit arithmetic operations in exchange for a bit more tricky and less readable code) but perhaps this is a symptom that indicates you need to take a look at some assumptions, or check/scale your inputs.

author: miguelvp
author_rank: Super Contributor
timestamp: December 25, 2014, 08:54:11 am
content: If he is concerned about values greater than 127 most likely he is treating the data as unsigned bytes.You can still do 2's complement substraction and adjust if the data is unsigned.

author: IanB
author_rank: Super Contributor
timestamp: December 25, 2014, 11:08:27 am
content: Quote from: miguelvp on December 25, 2014, 08:54:11 amYou can't "have a negative number" if the data is unsigned.I think actually the OP's question was confusing and unclear due to a lack of detail about the size and nature of the quantities involved and the intent of the operation.

author: Circlotron
author_rank: Super Contributor
timestamp: December 25, 2014, 12:07:05 pm
content: Quote from: IanB on December 25, 2014, 11:08:27 amIf A contains (positive) #150 the bit pattern is #%10010110.If we then ask it to BMI will it branch even though it is a positive number simply because the MSb is set?

author: Circlotron
author_rank: Super Contributor
timestamp: December 25, 2014, 12:15:36 pm
content: Quote from: mikerj on December 24, 2014, 09:10:31 amThat's what I'm now thinking too. A value > 127 wont set the carry bit but an underflow with the same bit pattern will.Good.

author: magetoo
author_rank: Frequent Contributor
timestamp: December 25, 2014, 03:26:30 pm
content: Quote from: Circlotron on December 25, 2014, 12:07:05 pmOkay, this is a bit long and rambling for a short question but maybe it'll help the pieces of the puzzle fit together better for someone who reads it.The way to look at it is that A, or any hardware register, never contains positive or negative numbers, but only bit patterns - like 10010110. The CPU designer has handed us machine instructions to interpret that bundle of bits as various kinds of data (positive/negative numbers, characters, offsets, pointers, whatever) but the underlying storage does not change.Higher level languages are different. There we have variables, and those can be defined to be only one thing or another ("foo is an unsigned int") but as far as the low-level hardware is concerned, that's just fiction. There's only sequences of bits there.So the answer to the question is "mu". Saying that "A contains positive 150" is like saying "A contains camel" - the right interpretation on a higher level, but meaningless as far as the hardware register is concerned.Machine instructions will interpret the bit patterns according to how they are designed to interpret them, and do so with no regard to what they "really are" - so understanding what instruction uses which interpretation is necessary.In this case (if the instruction set works as I assume), BMI would interpret 10010110 as a negative number. Doesn't mean that anything about the value changes, just that the bit pattern is seen that way by that particular instruction.

author: miguelvp
author_rank: Super Contributor
timestamp: December 25, 2014, 06:38:49 pm
content: Quote from: Circlotron on December 25, 2014, 12:15:36 pmJust curious, my code didn't work? because it does that and if the carry is set it will subtract from 0 (effectively 256 decimal) to adjust the result so you end up with the unsigned result.

author: Circlotron
author_rank: Super Contributor
timestamp: December 26, 2014, 05:02:53 am
content: Quote from: miguelvp on December 25, 2014, 06:38:49 pmI don't understand 2's complementing very well so I didn't try it. Sorry if I sound unappreciative

author: miguelvp
author_rank: Super Contributor
timestamp: December 26, 2014, 07:34:23 am
content: Quote from: Circlotron on December 26, 2014, 05:02:53 amI'm assuming you want to find the delta regardless on what value is bigger and both inputs treated as unsigned bytes.lets say A is 2and the other number is 152 and you want to find the absolute.2 - 152 in binary it will give you in binary 01101010 or 106 decimal after the 2's complement SUB opcode, but it will set the Carry flag indicating that it needs to be adjusted, now if you do the NEGA it will subtract 106 from 0 (really means 256 in this context) it will be 256 - 106 giving you the right answer 10010110 or 150 decimal if you treat all the inputs and the outputs as unsigned integers.Give it a try.Edit: if you do 152 - 2 the SUB opcode will come up with 150 and the Carry flag will be clear jumping over the adjustment.

author: Rasz
author_rank: Super Contributor
timestamp: December 27, 2014, 06:23:19 am
content: https://news.ycombinator.com/item?id=8797481http://www.tedunangst.com/flak/post/subtraction-is-not-comparison

author: miguelvp
author_rank: Super Contributor
timestamp: December 27, 2014, 08:45:17 am
content: Quote from: Rasz on December 27, 2014, 06:23:19 amNot sure what the second link states:Code:intcompar(int x, int y){return x - y;}QuoteSince the difference between them is 3975308642 (positive)But on 32 bit int system then the answer would be -137758612126, but that's for signed values and there is no way to have a positive result greater than 2147483647, but the problem on those links has no bearing to this problem since C can't access the Carry flag anyways.If the inputs are unsigned bytes with range [0,255] checking the carry flag and adjusting if set will produce the absolute delta between the inputs in the range of [0,255] as well.SUB instruction inhttp://cache.freescale.com/files/microcontrollers/doc/ref_manual/HCS08RMV1.pdfPage 284 states about the Carry Flag:QuoteOn the CMP opcode in page 242 it states exactly the same thing.

author: westfw
author_rank: Super Contributor
timestamp: December 27, 2014, 09:50:39 am
content: QuoteProbably true in some purist subset of theory, somewhere. But almost all computers that have a "compare" instruction define it along the lines of "works the same as the subtract instruction, except the actual result (the difference) is not used."For example, the ARM CortexM instruction set manual re CMP:Quote

author: miguelvp
author_rank: Super Contributor
timestamp: December 27, 2014, 09:59:06 am
content: Same as all processors I've encountered so far, CMP is the same as SUB but without storing the result and just updating the flags.