1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
| DATA SEGMENT MYSTR DB 20H DUP(?) ; FFFF = 65535 NEWSTR DB 20H DUP(?) ; 待增加的数字 MSG DB 'Please input your number: $' ADD_MSG DB 'Input the number you wanna add: $' OUTPUT_B DB 'The Binary form is: ' ; 20 + 16(MAX) OUTPUT_O DB 'The Octal form is: ' ; 20 + 6 OUTPUT_H DB 'The Hex form is: ' ; 20 + 4 ERROR_MSG DB 'ERROR: Your input is invalid, please enter an integer between 0 and 65535$' AGAIN DB 'Enter Y/y to continue Or any other letter to exit:$' ADDMORE DB 'Enter Y/y to continue to add a new number Or any other letter to exit:$' MAX_NUM DB '65535' RES DW 0 ; 字符串转换后的结果 NEWLINE DB 0AH, 0DH, '$' CLEAR DB 4000 DUP(' '), '$' FRAME_CHAR DB '*' COLOR_MSG DB 24h ; 绿底红字 COLOR_NUM DB 4Ah ; 红底绿字高亮 COLOR_FRAME DB 1CH ; 蓝底红字高亮 DATA ENDS
STACK SEGMENT STACK DB 20 DUP(?) TOP LABEL WORD ; 栈顶指针 STACK ENDS
CODE SEGMENT ASSUME CS: CODE, DS: DATA, SS: STACK START: MOV AX, DATA MOV DS, AX MOV AX, STACK MOV SS, AX LEA SP, TOP INPUT: LEA DX, MSG ; 输出提示信息 MOV AH, 09H INT 21H LEA DX, NEWLINE ; 换行 MOV AH, 09H INT 21H LEA DX, MYSTR ; 接收输入 MOV BX, DX MOV AL, 20 MOV DS:[BX], AL ; 字符串第一个字节存储最大字符个数 MOV AH, 0AH INT 21H XOR CH, CH MOV SI, DX ; 字符串存储地址 MOV CL, [SI + 1] ; 实际字符个数 ADD SI, 2 ; 指向第一个字符 READY: CALL CLEAR_FRONT ; 消除前缀0 CALL CHECK_LEN ; 检测数据长度 CALL CHECK_FIVE_DIGITS ; 检测五位数是否大于65535 SUB CL, 1 ; 循环LEN - 1次 XOR DX, DX ; 存放和 CMP CL, 0 JZ LAST ; 一位数不需要乘, 会导致CX = 0FFH STR_TO_NUM: MOV BL, [SI] INC SI SUB BL, 30H ; 不减先加可能会对CF造成影响 CALL CHECK_NUM ; 检测每一位数是否合规 ADD DL, BL ADC DX, 0 ; 进位 MOV AX, 0AH MUL DX MOV DX, AX LOOP STR_TO_NUM LAST: MOV BL, [SI] SUB BL, 30H ; 不减先加可能会对CF造成影响 CALL CHECK_NUM ; 检测每一位数是否合规 MOV AL, [SI] SUB AL, 30H ADD DL, AL ; 最后一个数不用乘 ADC DX, 0 MOV RES, DX CLEAN: LEA DX, CLEAR ; 清空整页 MOV AH, 09H INT 21H FRAME_UP: MOV AX, 0B866H ; 跳过前10行,跳过21个字符(80 - 36 - 2 >> 1) MOV ES, AX LEA SI, FRAME_CHAR MOV DI, 0AH ; 偏移地址 MOV CX, 38 ; 38个'*' PAINT_FRAME_UP: MOV AL, [SI] MOV ES:[DI], AL INC DI MOV AL, COLOR_FRAME MOV ES:[DI], AL INC DI LOOP PAINT_FRAME_UP FRAME_DOWN: MOV AX, ES ADD AX, 28H ; 加四行,段地址需要除以16 MOV ES, AX MOV DI, 0AH MOV CX, 38 PAINT_FRAME_DOWN: MOV AL, [SI] MOV ES:[DI], AL INC DI MOV AL, COLOR_FRAME MOV ES:[DI], AL INC DI LOOP PAINT_FRAME_DOWN FRAME_SIDE: MOV AX, 0B870H MOV ES, AX MOV DI, 0AH LEA SI, FRAME_CHAR MOV CX, 3 ; 3行 PAINT_FRAME_SIDE: PUSH CX PUSH DI PUSH AX MOV CX, 2 MOV ES, AX PAINT_ONE_LINE: MOV AL, [SI] MOV ES:[DI], AL INC DI MOV AL, COLOR_FRAME MOV ES:[DI], AL ADD DI, 72 ; 跳过36个字符 INC DI LOOP PAINT_ONE_LINE POP AX ADD AX, 0AH ; 0A * 16 = 160 POP DI POP CX LOOP PAINT_FRAME_SIDE MOV AX, 0B870H ; 段地址,跳过前11行,跳过22个字符 MOV ES, AX LEA SI, OUTPUT_B MOV DI, 0CH MOV CX, 20 COLORFUL_OUTPUT_B: ; 输出二进制提示信息 MOV AL, [SI] MOV ES:[DI], AL INC DI MOV AL, COLOR_MSG MOV ES:[DI], AL INC SI INC DI LOOP COLORFUL_OUTPUT_B MOV CX, 16 MOV BX, RES PRINT_B: ROL BX, 1 ; 循环左移一位,将最高位移到最低位 MOV AX, BX AND AL, 01H ; 将除了最低位的其他位置清零 ADD AL, 30H MOV ES:[DI], AL INC DI MOV AL, COLOR_NUM MOV ES:[DI], AL INC DI LOOP PRINT_B CLC ; CF清零 MOV AX, 0B87AH ; 段地址,跳过前12行,跳过22个字符 MOV ES, AX LEA SI, OUTPUT_O MOV DI, 0CH MOV CX, 20 COLORFUL_OUTPUT_O: ; 输出八进制提示信息 MOV AL, [SI] MOV ES:[DI], AL INC DI MOV AL, COLOR_MSG MOV ES:[DI], AL INC SI INC DI LOOP COLORFUL_OUTPUT_O MOV AX, RES ; 第一个八进制 ROL AX, 1 CLC ; CF清零 AND AL, 01H ADD AL, 30H MOV ES:[DI], AL INC DI MOV AL, COLOR_NUM MOV ES:[DI], AL INC DI MOV CX, 5 MOV BL, 0 ; 4,7,10,13,16 PRINT_O: PUSH CX MOV AX, RES ; 第二三四五六对应八进制 MOV CL, 4 ADD CL, BL ROL AX, CL ADD BL, 3 AND AL, 00000111B ADD AL, 30H MOV ES:[DI], AL INC DI MOV AL, COLOR_NUM MOV ES:[DI], AL INC DI POP CX LOOP PRINT_O CLC ; CF清零 MOV AX, 0B884H ; 段地址,跳过前13行,跳过22个字符 MOV ES, AX LEA SI, OUTPUT_H MOV DI, 0CH MOV CX, 20 COLORFUL_OUTPUT_H: ; 输出十六进制提示信息 MOV AL, [SI] MOV ES:[DI], AL INC DI MOV AL, COLOR_MSG MOV ES:[DI], AL INC SI INC DI LOOP COLORFUL_OUTPUT_H MOV CX, 4 MOV BL, 4 ; 步幅 PRINT_H: PUSH CX MOV DX, RES MOV CL, BL ADD BL, 4 ROL DX, CL CLC ; CF清零 AND DL, 00001111B CALL CONVERT MOV ES:[DI], DL INC DI MOV DL, COLOR_NUM MOV ES:[DI], DL INC DI POP CX LOOP PRINT_H ADDAGIN: LEA DX, ADDMORE MOV AH, 09H INT 21H LEA DX, NEWLINE ; 换行 MOV AH, 09H INT 21H MOV AH, 01H INT 21H CMP AL, 'Y' ; 比较输入之前换行会修改AL JZ INPUT_AGAIN CMP AL, 'y' JZ INPUT_AGAIN OVER: LEA DX, NEWLINE ; 换行 MOV AH, 09H INT 21H MOV AH, 4CH INT 21H INPUT_AGAIN: LEA DX, NEWLINE ; 输入Y/y跳转之后再换行 MOV AH, 09H INT 21H LEA DX, ADD_MSG MOV AH, 09H INT 21H LEA DX, NEWLINE ; 换行 MOV AH, 09H INT 21H LEA DX, NEWSTR MOV BX, DX MOV AL, 20 ; 设置最大字符数 MOV DS:[BX], AL MOV AH, 0AH INT 21H MOV SI, DX ; 指向新输入的字符串 MOV CL, [SI + 1] ; 新输入的字符串长度 ADD SI, 2 ; 指向第一个字符 CALL CLEAR_FRONT_NEW ; 清除新字符串的前缀零 ADD_NEW_TO_FIVE: CMP CL, 05H ; 比较新字符串是否是五位数 JZ ADD_OLD_TO_FIVE JA ERROR PUSH SI ; 存储新字符串起始位置 PUSH SI ADD SI, 4 MOV DI, SI ; DI指向五位数最后一位 POP SI XOR CH, CH PUSH CX DEC CX ADD SI, CX ; SI指向当前字符串最后一位 POP CX XOR CH, CH PUSH CX MOVE: MOV AL, [SI] MOV [DI], AL ; 依次后移 DEC SI DEC DI LOOP MOVE POP CX POP SI PUSH SI MOV AL, 5 SUB AL, CL ; AL = 5 - CL -> 补零个数 MOV CL, AL ; 剩余位置补零 XOR CH, CH ADD_ZERO: MOV BYTE PTR [SI], 30H INC SI LOOP ADD_ZERO POP SI ; 新字符串的起始位置已经在CLEAR_FRONT中存入了最大长度字段 MOV CL, 05H ; 最终长度为5 LEA DI, NEWSTR MOV [DI + 1], CL ; 实际长度修改为5 ADD_OLD_TO_FIVE: LEA SI, MYSTR MOV CL, [SI + 1] ; 取出旧字符串实际长度 CMP CL, 05H JZ ADD_NEW_TO_OLD MOV SI, DS:[SI] ; SI指向旧字符串第一个字符 AND SI, 0FFH ; 高位字节清零 PUSH SI PUSH SI ADD SI, 4 MOV DI, SI ; DI指向五位数最后一位 POP SI PUSH CX DEC CL XOR CH, CH ADD SI, CX ; SI指向当前字符串最后一位 POP CX XOR CH, CH PUSH CX MOVE_OLD: MOV AL, [SI] MOV [DI], AL ; 依次后移 DEC SI DEC DI LOOP MOVE_OLD POP CX POP SI PUSH SI XOR CH, CH MOV AL, 5 SUB AL, CL MOV CL, AL ; 剩余位置补零 ADD_OLD_ZERO: MOV BYTE PTR [SI], 30H INC SI LOOP ADD_OLD_ZERO POP SI MOV CL, 05H ; 最终长度为5 LEA DI, MYSTR MOV [DI + 1], CL ; 实际长度修改为5 ADD_NEW_TO_OLD: LEA SI, NEWSTR MOV SI, [SI] ; 指向第一个字符 AND SI, 0FFH LEA DI, MYSTR MOV DI, [DI] ; 指向第一个字符 AND DI, 0FFH ADD SI, 4 ; SI指向新字符串第五位字符 ADD DI, 4 ; DI指向旧字符串第五位字符 MOV CX, 05H PUSH SI SUB_NEW_TO_NUM: ; 避免因为新旧字符串都有30H导致对CF造成影响 SUB BYTE PTR [SI], 30H ; 如果是WORD PTR, 30H高位为0,也没有影响 DEC SI LOOP SUB_NEW_TO_NUM POP SI CMP BYTE PTR [SI-4], 6 ; 判断五位数第一个数字是否合法,只要保证合法就不会发生五位数溢出 JA ERROR MOV CX, 05H ADD_NEW_AND_OLD: MOV AL, [SI] ADD [DI], AL MOV AL, [DI] CMP AL, 39H JA ABOVE_NINE NEXT: DEC SI DEC DI LOOP ADD_NEW_AND_OLD XOR CH, CH LEA SI, MYSTR ; 字符串存储地址 MOV CL, [SI + 1] ; 实际字符个数 MOV SI, [SI] ; 指向第一个字符 AND SI, 0FFH JMP READY ABOVE_NINE: ; 超出39,该位减十,高位加一 SUB AL, 0AH MOV [DI], AL MOV BX, DI DEC BX INC BYTE PTR [BX] JMP NEXT CONVERT: CMP DL, 0AH JB BELOW ADD DL, 07H BELOW: ADD DL, 30H RET CLEAR_FRONT: CMP CL, 01H JZ FINISH MOV AL, [SI] CMP AL, 30H ; '0' JNE FINISH INC SI ; 跳过当前字符 DEC CL ; 长度减一 JMP CLEAR_FRONT FINISH: LEA DI, MYSTR MOV [DI], SI ; 将第一个字符的位置存储到字符串的最大容量字段 MOV [DI + 1], CL ; 将修改后的长度填入字符串实际长度字段 RET CLEAR_FRONT_NEW: CMP CL, 01H JZ FINISH_NEW MOV AL, [SI] CMP AL, 30H ; '0' JNE FINISH_NEW INC SI ; 跳过当前字符 DEC CL ; 长度减一 JMP CLEAR_FRONT_NEW FINISH_NEW: LEA DI, NEWSTR MOV [DI], SI ; 将第一个字符的位置存储到字符串的最大容量字段 MOV [DI + 1], CL ; 将修改后的长度填入字符串实际长度字段 RET CHECK_LEN: CMP CL, 05H ; 最大65535,5位 JA ERROR RET CHECK_FIVE_DIGITS: PUSH CX ; 数据长度, PUSH至少是WORD PUSH SI ; 字符串指针 CMP CX, 05H JB CHECK_FIVE_FINISH ; 不到五位不用比较 LEA DI, MAX_NUM MOV CX, 05H CHECK_FIVE: MOV AL, [DI] CMP AL, [SI] JB ERROR JA CHECK_FIVE_FINISH INC DI INC SI LOOP CHECK_FIVE CHECK_FIVE_FINISH: POP SI POP CX RET CHECK_NUM: CMP BL, 09H ; 保证每位数字在0~9 JA ERROR RET ERROR: LEA DX, NEWLINE ; 换行, 保留用户输入 MOV AH, 09H INT 21H LEA DX, ERROR_MSG ; 错误提示 MOV AH, 09H INT 21H LEA DX, NEWLINE ; 换行 MOV AH, 09H INT 21H LEA DX, AGAIN MOV AH, 09H INT 21H LEA DX, NEWLINE ; 换行 MOV AH, 09H INT 21H MOV AH, 01H INT 21H CMP AL, 'Y' JZ RESTART CMP AL, 'y' JZ RESTART LEA DX, NEWLINE ; 换行 MOV AH, 09H INT 21H JMP OVER RESTART: LEA DX, CLEAR ; 清空整页 MOV AH, 09H INT 21H JMP INPUT CODE ENDS END START
|