It's especially ugly on ones complement machines.
-- Shmuel (Seymour J.) Metz http://mason.gmu.edu/~smetz3 ________________________________________ From: IBM Mainframe Assembler List [ASSEMBLER-LIST@LISTSERV.UGA.EDU] on behalf of Ian Worthington [00000c9b78d54aea-dmarc-requ...@listserv.uga.edu] Sent: Friday, April 15, 2022 3:02 AM To: ASSEMBLER-LIST@LISTSERV.UGA.EDU Subject: Re: Signed/unsigned operations Both signed and unsigned integer operations are required to either wrap or give undefined results in C. To my mind this is a horrible problem which gets kicked down the road by the expansion of the size of variable size every few years, presumably accompanies by the sacrificing of farmyard animals to some deity or other.. But I'm pleased(!) to see it's now being exploited as an attack vector and there's a proposal in C23 to formalise a checked integer macro (though just for addition, subtraction, and multiplication, apparently on the basis that Java omits checking for division so the C standards people won't do it either?). The implementation I've seen so far actually depends on the implementation behaving in a sensible fashion and wrapping/truncating rather giving a totally unpredictable result, so we'll have to see what happens with the vote on this. This is actually what's driving this exploration. I can, I think, better implement checked arithmetic in 32 and 64 bit modes using functions akin to the proposed C23 standard, but using the hardware to do the checking, eg: bool ckd_add_u32(__uint32_t *result, __uint32_t u32a, __uint32_t u32b, bool abort) { __uint32_t ccpm; const __uint32_t carrybit = 0x20000000; __uint32_t sum = u32a; asm("alr %[r1],%[r2] \n\t" "ipm %[r3]" : [r1] "+r" (sum), // output [r3] "=r" (ccpm) : [r2] "r" (u32b) // input : // clobbers ); bool overflow = (ccpm & carrybit) != 0; // check if carry bit set char msgbuf[100]; sprintf( msgbuf, "a: %11u, b: %11u, sum: %11u ccpm: 0x%08x, overflow: %s", u32a, u32b, sum, ccpm, overflow ? "true" : "false" ); wtopc_text( msgbuf ); if (abort && overflow) { serrc_op( (enum t_serrc)(SERRC_EXIT), 0xDEAD00, "INTEGER OVERFLOW OCCURRED", NULL ); } *result = sum; return overflow; } which I think is relatively efficient, at least if inlined. 16, and 8, bit operations are, I think, a bit more tricky to do like this and might have to use post-operation checks. I need to have a think about that. Best wishes / Mejores deseos / Meilleurs vœux Ian ... On Thursday, April 14, 2022, 06:25:11 PM GMT+2, Paul Gilmartin <00000014e0e4a59b-dmarc-requ...@listserv.uga.edu> wrote: On Apr 14, 2022, at 09:21:28, Robin Vowels wrote: > > On 2022-04-15 00:31, Seymour J Metz wrote: >> The S/360 architecture uses two's complement arithmetic, and that >> remains the case through z. Accordingly, signed and unsigned >> arithmetic are the same except for the condition code, except when >> sign extension is an issue, e.g., adding a word to a grande register.. > > If the relevant overflow mask bit is set, > integer overflow causes an interrupt. > A couple C implementations (other than XL C/C++ which I haven't checked) require integer overflow interrupts disabled at runtime. ANSI C requires unsigned operations to be performed with modulo arithmetic. For integer overflow either (I don't recall which) the behavior is unpredictable, allowing an interrupt, or the value or the result is unpredictable, not allowing interrupt. Pre-ANSI C specified unsigned-preserving, so: -1 > (unsigned) 0. /* Ugh! */ ANSI C specified value-preserving, so: -1 < (unsigned) 0 -- gil