Here's a simple C++ program:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> a = {7};
int b = 7;
if (a[0] > 6) {
cout << "a bigger than 6" << endl;
}
if (b > 6) {
cout << "b bigger than 6" << endl;
}
return 0;
}
Upon compiling with gdb -g ... and generating assembly with objdump --source-comment=";SOURCE: " -wlCS ..., here's the conditionals' x86 assembly code:
;SOURCE: if (a[0] > 6) {
1321: 48 8d 45 b0 lea -0x50(%rbp),%rax
1325: be 00 00 00 00 mov $0x0,%esi
132a: 48 89 c7 mov %rax,%rdi
132d: e8 82 02 00 00 call 15b4 <std::vector<int, std::allocator<int> >::operator[](unsigned long)>
1332: 8b 00 mov (%rax),%eax
1334: 83 f8 06 cmp $0x6,%eax
1337: 0f 9f c0 setg %al
133a: 84 c0 test %al,%al
133c: 74 2b je 1369 <main+0xc0>
and
;SOURCE: if (b > 6) {
1369: 83 7d ac 06 cmpl $0x6,-0x54(%rbp)
136d: 7e 2b jle 139a <main+0xf1>
In the second example, the value of b is simply compared with 6 and the jump statement skips ahead if b <= 6.
In the first example, after the value 7 is read from the vector a, it is stored in %eax and compared with 6. I see that setg will set %al to match the "greater" condition (ZF=0 and SF=OF), test will set the zero flag to the inverse of %al (in this case), and je will jump if the zero flag is set (indicating that a[0] was not greater than 6).
My question is why setg, test, and je are needed here. Couldn't the latter portion of the first example be implemented in the same way as the second one, using only cmp(l) and jle? Would this potentially be faster?
Note: this doesn't have anything to do with objdump; the output of gdb -S contains the same instructions.
g++ (Ubuntu 11.3.0-1ubuntu1\~22.04.1) 11.3.0
GNU objdump (GNU Binutils for Ubuntu) 2.38