Subtracting 0x8000 From An Int - Stack Overflow

Just browsing Stack Overflow? Help us improve your experience. Sign up for research
    1. Home
    2. Questions
    3. Tags
    4. Users
    5. Companies
    6. Labs
    7. Jobs
    8. Discussions
    9. Collectives
    10. Communities for your favorite technologies. Explore all Collectives

  1. Teams

    Ask questions, find answers and collaborate at work with Stack Overflow for Teams.

    Try Teams for free Explore Teams
  2. Teams
  3. Ask questions, find answers and collaborate at work with Stack Overflow for Teams. Explore Teams

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Get early access and see previews of new features.

Learn more about Labs Subtracting 0x8000 from an int Ask Question Asked 10 years, 10 months ago Modified 10 years, 10 months ago Viewed 3k times 2

I am reverse engineering some old C, running under Win95 (yes, in production) appears to have been compiled with a Borland compiler (I don't have the tool chain).

There is a function which does (among other things) something like this:

static void unknown(int *value) { int v = *value; v-=0x8000; *value = v; }

I can't quite work out what this does. I assume 'int' in this context is signed 32 bit. I think 0x8000 would be unsigned 32bit int, and outside the range of a signed 32 bit int. (edit - this is wrong, it is outside of a signed 16 bit int)

I am not sure if one of these would be cast first, and how the casting would handle overflows, and/or how the subtraction would handle the over flow.

I could try on a modern system, but I am also unsure if the results would be the same.

Edit for clarity:

1: 'v-=0x8000;' is straight from the original code, this is what makes little sense to me. v is defined as an int.

2: I have the code, this is not from asm.

3: The original code is very, very bad.

Edit: I have the answer! The answer below wasn't quite right, but it got me there (fix up and I'll mark it as the answer).

The data in v is coming from an ambiguous source, which actually seems to be sending unsigned 16 bit data, but it is being stored as a signed int. Latter on in the program all values are converted to floats and normalised to an average 0 point, so actual value doesn't matter, only order. Because we are looking at an unsigned int as a signed one, values over 32767 are incorrectly placed below 0, so this hack leaves the value as signed, but swaps the negative and positive numbers around (not changing order). End results is all numbers have the same order (but different values) as if they were unsigned in the first place.

(...and this is not the worst code example in this program)

Share Improve this question Follow edited Jan 24, 2014 at 0:53 Bruce asked Jan 23, 2014 at 23:49 Bruce's user avatar BruceBruce 231 silver badge4 bronze badges 9
  • 2 Are you sure the code is correct? Surely it should say *value instead of value. – interjay Commented Jan 23, 2014 at 23:52
  • 1 You mentioned reverse engineering. Is the code you wrote in C maybe converted from assembler? In assember SUB doesn't only subtract, but also sets cpu flags that are used in conditional jumps. The word size is probably 16bit, so this could be a check for something. – typ1232 Commented Jan 23, 2014 at 23:55
  • > Surely it should say *value instead of value - Yep, sorry typed that up quickly, that part isn't the unknown bit. – Bruce Commented Jan 23, 2014 at 23:56
  • This is not converted from asm, I have the original code. It is worth noting that the original code is bad and has many mistakes. – Bruce Commented Jan 23, 2014 at 23:58
  • 2 So the code is v=-0x8000 verbatim? Because that's very different from what you've posted in your question. (Your question contains -=, and your last comment contains =-.) – Ken White Commented Jan 24, 2014 at 0:01
| Show 4 more comments

2 Answers 2

Sorted by: Reset to default Highest score (default) Trending (recent votes count more) Date modified (newest first) Date created (oldest first) 3

In Borland C 3.x, int and short were the same: 16 bits. long was 32-bits.

A hex literal has the first type in which the value can be represented: int, unsigned int, long int or unsigned long int.

In the case of Borland C, 0x8000 is a decimal value of 32768 and won't fit in an int, but will in an unsigned int. So unsigned int it is.

The statement v -= 0x8000 ; is identical to v = v - 0x8000 ;

On the right-hand side, the int value v is implicitly cast to unsigned int, per the rules, the arithmetic operation is performed, yielding an rval that is an unsigned int. That unsigned int is then, again per the rules, implicitly cast back to the type of the lval.

So, by my estimation, the net effect is to toggle the sign bit — something that could be more easily and clearly done via simple bit-twiddling: *value ^= 0x8000 ;.

Share Improve this answer Follow edited Jan 24, 2014 at 0:51 answered Jan 24, 2014 at 0:20 Nicholas Carey's user avatar Nicholas CareyNicholas Carey 73.9k16 gold badges95 silver badges136 bronze badges 5
  • @PeterGibson. Fixed it for you. Still won't fit in a 16-bit signed int. Clearly, I haven't had enough coffee today :D – Nicholas Carey Commented Jan 24, 2014 at 0:30
  • Thanks, drinking my cup now :) Also doesn't this toggle the sign bit rather than clearing it? – Peter Gibson Commented Jan 24, 2014 at 0:31
  • So the negative on 0x8000 has no effect? I suspect this but can't be sure. If v is negative this results in a inverted positive (-1=>32767, -32768->0) number (as you describe, clearing the sign bit). If it is positive in the first place doesn't it do the reverse (make negative and invert). – Bruce Commented Jan 24, 2014 at 0:38
  • I just tested it in Visual C. Coercing things to short and unsigned short. It does indeed appear toggle the sign bit. Answer amended. – Nicholas Carey Commented Jan 24, 2014 at 0:53
  • @PeterGibson Note: 0x8000 is an unsigned with a value of 32,768. 32768 is a long with same value. – chux Commented Sep 23, 2016 at 19:21
Add a comment | 1

There is possibly a clue on this page http://www.ousob.com/ng/borcpp/nga0e24.php - Guide to Borland C++ 2.x ( with Turbo C )

There is no such thing as a negative numeric constant. If a minus sign precedes a numeric constant it is treated as the unary minus operator, which, along with the constant, constitutes a numeric expression. This is important with -32768, which, while it can be represented as an int, actually has type long int, since 32768 has type long. To get the desired result, you could use (int) -32768, 0x8000, or 0177777.

This implies the use of two's complement for negative numbers. Interestingly, the two's complement of 0x8000 is 0x8000 itself (as the value +32768 does not fit in the range for signed 2 byte ints).

So what does this mean for your function? Bit wise, this has the effect of toggling the sign bit, here are some examples:

f(0) = f(0x0000) = 0x8000 = -32768 f(1) = f(0x0001) = 0x8001 = -32767 f(0x8000) = 0 f(0x7fff) = 0xffff

It seems like this could be represented as val ^= 0x8000, but perhaps the XOR operator was not implemented in Borland back then?

Share Improve this answer Follow edited Jan 24, 2014 at 0:53 answered Jan 24, 2014 at 0:02 Peter Gibson's user avatar Peter GibsonPeter Gibson 19.5k7 gold badges62 silver badges64 bronze badges 4
  • That would make sense. 0x8000 is 32768 in decimal. And 0177777 (octal) is 65535 in decimal.user1508519 Commented Jan 24, 2014 at 0:06
  • This really helps, but I am still not sure what the end result is to the int. – Bruce Commented Jan 24, 2014 at 0:17
  • Thanks this is correct, I just saw Nicholas Carey's edit first. – Bruce Commented Jan 24, 2014 at 1:11
  • The XOR operator was implemented in Borland back then. – chux Commented Sep 23, 2016 at 19:46
Add a comment |

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid …

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

Draft saved Draft discarded

Sign up or log in

Sign up using Google Sign up using Email and Password Submit

Post as a guest

Name Email

Required, but never shown

Post Your Answer Discard

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.

  • The Overflow Blog
  • Your docs are your infrastructure
  • Featured on Meta
  • More network sites to see advertising test [updated with phase 2]
  • We’re (finally!) going to the cloud!
  • Call for testers for an early access release of a Stack Overflow extension...
7 Subtracting two numbers without using '-' operator 4 Subtracting Decimal Values (Assembly) 3 int $0x80 in Programming From The Ground Up 1 subtracting two unsigned 32-bit integers and assign to 64-bit signed integer 0 Decrement unsigned integer by 1 0 Subtraction with ReadInt 0 Adding 0 at starting of int value in c 0 Subtraction over ranges of bits 1 Subtracting 1 from 0 in 8 bit binary 1 Subtracting digits from an integer right to left

Hot Network Questions

  • Polynomial.java - a Java class for dealing with polynomials with BigDecimal coefficients
  • Why is Anarchism not considered fundamentally against the "democratic order" in Germany?
  • Why did the angel strain or dislocate Yaakov's hip-socket?
  • Identifying a TNG episode where Dr. Pulaski instructs another doctor on a sling
  • Is there a symbol for the Hyper key?
  • Will a laptop battery that stays connected to its charger be damaged?
  • How do I go about rebranding a fully deleted project that used to have a GNU General Public License v3.0 but is now fully inaccessible
  • Static vs dynamic certificate pinning
  • Can you please advise on kerning?
  • Is there a cryptographic method that can only decrypt for a certain range of seeds?
  • How much ebikes actually benefit from ebike specific wheels, tires, and forks?
  • How to say "Each one of the following" in German?
  • Shell Script to Normalize the data
  • Table structure with multiple foreign keys and values
  • Schrödinger's cat ++
  • Being honest with rejection vs. preparing applicant for future possibility
  • How can I politely decline a request to join my project by a free rider professor
  • What's a good way to append a nonce to ciphertext in Python for AES GCM in Python?
  • Do market-makers often act as a taker in other markets or assets while hedging?
  • What is this insect found in an apartment in Brazil?
  • If someone’s words are likely to be disregarded, how to describe the quality of “meaning” they lack?
  • Sorites paradox and emergence
  • In GR, what is Gravity? A force or curvature of spacetime?
  • Clarification and Proof of Inequality (8.11) in Analytic Number Theory by Iwaniec and Kowalski
more hot questions Question feed Subscribe to RSS Question feed

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

lang-c

Từ khóa » C 0x8000