如何用NASM汇编写一个静态资源服务器?(六)、终章,启动参数

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

前言

我们已经完成了一个基本的http服务器,但是端口和root路径是写死的,如果需要更改,还的重新编译,那么,我们可以利用启动参数来动态绑定,解决这个问题。

比如最终我们可以用下面方式启动的程序。

./socket 7070 /home/www/

启动参数也是放在栈中的,从esp开始的第一个4字节表示参数个数,如果什么也不传,则是1,因为默认会有一个参数是程序的启动路径,从偏移12个字节开始,是我们传递的参数,为什么是偏移12而不是8呢?因为我们的程序从单独的方法中加载参数,调用方法时,会把返回地址也压入栈,当ret时候会弹出,所以,会偏移12字节。

注意这里表示参数是一个字符指针。

完整程序地址:https://github.com/houxinlin/nasm-examples/tree/main/http-server

加载端口

这个函数用来加载端口号,需要把ascii转换int,还有就是需要反转,因为在bind函数调用时,端口需要反序存储,调用toInt后会把端口号转换为int并且放入eax中,然后把eax的低8位放入ebx的高8位,eax的高8位放入ebx的低8位。

loadBindPort:
    mov esi,[esp+12]   ;;从启动参数中加载端口
    call reversal     ;;反转端口字节
    ret

reversal:
    call toInt
    mov ebx,0
    mov bh,al
    mov bl,ah
    ret
toInt:
    mov eax,0
    mov ecx,0
_nextToInt:    
    cmp byte[esi+ecx],0    
    je _finishToInt
    mov edx,0
    mov dl, [esi+ecx]
    sub dl,48  ;;edx中保存当前ascii转换的数组
    push edx
    mov ebx,10
    mul ebx
    pop edx
    add eax,edx
    inc ecx
    jmp _nextToInt
_finishToInt:
    ret       

加载root路径

loadBindRoot比较简单,首先获取第二个参数长度,然后通过movsb复制到root变量中即可。


loadBindRoot:
    mov esi ,[esp+16]
    call getStringLength
    mov ecx,eax
    mov edi,root
    rep    movsb
    ret

然后在主程序中调用即可

CMAIN:
    xor     eax, eax
    xor     ebx, ebx
    xor     edi, edi
    xor     esi, esi

    ;push   default_path
    ;push   default_port
    ;push   default_media
    ;push   3
 
    call   loadBindPort
    mov   dword[port],ebx
    call   loadBindRoot

- END -


原文始发于微信公众号(十四个字节):如何用NASM汇编写一个静态资源服务器?(六)、终章,启动参数