void out_char(char c)
{
/*403370: b00001c1 adrp x1, 43c000 <memcpy@GLIBC_2.17>
403374: 9121c021 add x1, x1, #0x870 // x1=0x43c870
403378: 12001c00 and w0, w0, #0xff // w0=c&0xff
40337c: b9401022 ldr w2, [x1, #16] // w2=[0x43c880]=charlen
403380: 34000242 cbz w2, 4033c8 <ferror@plt+0x14e8>
if (charlen == 0) {
// cbz 4033c8
}
403384: 51000442 sub w2, w2, #0x1 // w2=charlen-1
403388: b00001c3 adrp x3, 43c000 <memcpy@GLIBC_2.17>
charlen = charlen--;
40338c: 910a2064 add x4, x3, #0x288 // x4=0x43c288=&cur_x
403390: b9001022 str w2, [x1, #16] // charlen=charlen-1
charlen = charlen; // 通过这两处的不同执行点,看不到if ((c & 0x80) == 0) 和 charlen = 4 的代码逻辑,
// charlen--在c代码的逻辑中都会执行,但在汇编中执行流程被优化改变了。
// 无论(c & 0x80)等0或不等于0,charlen都等于1,c代码逻辑会执行charlen--,所以charlen=0,
// 而汇编代码是因(charlen == 0)才到 4033c8 执行流程的,没有了 charlen-- 操作,故而
// (c & 0x80)等0或不等于0 (不包含其它if时), charlen 都是 0。
403394: b9400481 ldr w1, [x4, #4] // x1=[0x43c28c]=trunc
403398: 34000121 cbz w1, 4033bc <ferror@plt+0x14dc>
40339c: b9428862 ldr w2, [x3, #648] // w2=[0x43c288]=cur_x
4033a0: b9400881 ldr w1, [x4, #8] // x1=[0x43c290]=output_width
4033a4: 6b01005f cmp w2, w1 // w2=cur_x, w1=output_width
4033a8: 540000ad b.le 4033bc <ferror@plt+0x14dc>
if (!trunc || cur_x <= output_width) {
// b.le 4033bc
putchar(c);
}
else {
4033ac: 11000421 add w1, w1, #0x1 // w1=output_width+1
4033b0: 6b01005f cmp w2, w1 // cur_x ? output_width+1
4033b4: 54000300 b.eq 403414 <ferror@plt+0x1534> // b.none
if (trunc && (cur_x == output_width + 1) {
// b.eq 403414
putchar('+');
}
}
4033b8: d65f03c0 ret*/
}
/*4033bc: b00001c1 adrp x1, 43c000 <memcpy@GLIBC_2.17>
4033c0: f9442821 ldr x1, [x1, #2128] // x1=[0x43c850]
4033c4: 17fff9bb b 401ab0 <putc@plt>
4033c8: 373800c0 tbnz w0, #7, 4033e0 <ferror@plt+0x1500>
if ((c & 0x80) != 0) {
// tbnz 4033e0
}
4033cc: b00001c3 adrp x3, 43c000 <memcpy@GLIBC_2.17>
4033d0: b9428864 ldr w4, [x3, #648] // w4=[0x43c288]=cur_x
4033d4: 11000484 add w4, w4, #0x1 // w4=cur_x+1
4033d8: b9028864 str w4, [x3, #648] // [0x43c288]=cur_x+1
cur_x++;
4033dc: 17ffffec b 40338c <ferror@plt+0x14ac>
4033e0: 121b0803 and w3, w0, #0xe0 // w3=c&0xe0
4033e4: 52800022 mov w2, #0x1 // charlen=1
charlen = 1;
4033e8: 7103007f cmp w3, #0xc0
4033ec: 54ffff00 b.eq 4033cc <ferror@plt+0x14ec> // b.none
if ((c & 0xe0) == 0xc0) {
// b.eq 4033cc
}
4033f0: 121c0c03 and w3, w0, #0xf0 // w3=c*0xf0
4033f4: 52800042 mov w2, #0x2 // charlen=2
charlen = 2;
4033f8: 7103807f cmp w3, #0xe0
4033fc: 54fffe80 b.eq 4033cc <ferror@plt+0x14ec> // b.none
if ((c & 0xf0) == 0xe0) {
// b.eq 4033cc
}
403400: 121d1003 and w3, w0, #0xf8 // w3=c*0xf8
403404: 52800062 mov w2, #0x3 // charlen=3
charlen = 3;
403408: 7103c07f cmp w3, #0xf0
40340c: 1a8213e2 csel w2, wzr, w2, ne // ne = any
if ((c & 0xf8) == 0xf0) {
charlen = 3;
}
403410: 17ffffef b 4033cc <ferror@plt+0x14ec>
403414: b00001c1 adrp x1, 43c000 <memcpy@GLIBC_2.17>
403418: 52800560 mov w0, #0x2b // #43='+'
40341c: f9442821 ldr x1, [x1, #2128]
403420: 17fff9a4 b 401ab0 <putc@plt>*/
static void out_char(char c)
{
// 403370
if (charlen == 0) { /* "new" character */
// 4033c8 -> 40338c
if ((c & 0x80) == 0) {
charlen = 1; /* ASCII */
// 4033e8
} else if ((c & 0xe0) == 0xc0) { /* 110.. 2 bytes */
charlen = 2;
// 4033f8
} else if ((c & 0xf0) == 0xe0) { /* 1110.. 3 bytes */
charlen = 3;
// 403408
} else if ((c & 0xf8) == 0xf0) { /* 11110.. 4 bytes */
charlen = 4;
} else {
charlen = 1;
}
cur_x++; /* count first byte of whatever it is only */
}
// 403384
charlen--; // 汇编代码有点难理解。
// 403394
if (!trunc || cur_x <= output_width)
putchar(c);
// 4033ac
else {
if (trunc && (cur_x == output_width + 1))
putchar('+');
}
}